zephir.lib_zephir

Package zephir :: Module lib_zephir |
[frames] | no frames]

# Source Code for Module zephir.lib_zephir

      1  # -*- coding: UTF-8 -*-
      2  ###########################################################################
      3  # Eole NG - 2007
      4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
      5  # Licence CeCill  cf /root/LicenceEole.txt
      6  # eole@ac-dijon.fr
      7  #
      8  # lib_zephir.py
      9  #
     10  # librairie de fonctions pour le client Zephir
     11  #
     12  ###########################################################################
     13
     14  registered = 1
     15  try:
     16      import zephir.zephir_conf.zephir_conf as config
     17  except:
     18      registered = 0
     19  import os, sys, time, socket, getpass
     20  from creole.cfgparser import EoleDict
     21  from creole.config import eoledirs, eoleroot, eole_module, rsyslog_request_template
     22  from creole.utils import print_orange, print_red, print_green
     23  from creole.eosfunc import load_container_var
     24  from creole.cert import gen_request, gen_privkey
     25  from pyeole.service import service_out, service_code
     26  from pyeole.process import system_code, system_out
     27  from glob import glob
     28  import traceback
     29  # imports locaux
     30  from zephir.eolerpclib import xmlrpclib, EoleProxy
     31  from zephir.prelude_options import get_options
     32
     33  # valeurs par défaut pour la fonction de saisie d'enregistrement_zephir
     34  defaults = {'timeout':30,'interf':'eth0'}
     35
     36  # définition de l'encodage du texte
     37  charset = 'UTF-8'
     38  # répertoire publique d'uucp
     39  public_dir = '/var/spool/uucppublic'
     40  # définition du proxy XMLRPC
     41  eole_dir = '/usr/share/eole'
     42  zephir_dir = '/usr/share/zephir'
     43  new_addr_file = os.path.join(zephir_dir, 'zephir_conf', 'new_pubkey')
     44  # mode de sauvegarde des données locales
     45  save_modes = {0:"Tout",
     46                1:"configuration",
     47                2:"configuration + patchs/dicos/templates",
     48                3:"fichiers divers locaux",
     49               }
     50  # variables de gestion des conteneurs
     51  container_vars = load_container_var()
     52
     53  # recherche du répertoire du module zephir
     54  import zephir as zephir_lib
     55  zephir_path = os.path.dirname(zephir_lib.__file__)
     56
     57  # redéfinition de la classe pour supporter les timeouts
     58 -class TransportEole(xmlrpclib.SafeTransport):
     59
     60 -    def _parse_response(self, file, sock):
     61          """lit et parse la réponse du serveur
     62          modifié pour ne pas bloquer sur la lecture (file.read)
     63          dans le cas de l'utilisation de ssl
     64          """
     65          # read response from input file/socket, and parse it
     66
     67          p, u = self.getparser()
     68
     69          while 1:
     70              if sock:
     71                  response = sock.recv(1024)
     72              else:
     73                  response = file.read(1024)
     74              if not response:
     75                  break
     76              if self.verbose:
     77                  print "body:", repr(response)
     78              p.feed(response)
     79              if len(response) < 1024:
     80                  break
     81
     82          file.close()
     83          p.close()
     84
     85          return u.close()
     86
     87  try:
     88      if os.path.isdir('/var/lib/zephir'):
     89          # on permet un temps d'attente plus long lors des requêtes sur Zephir
     90          socket.setdefaulttimeout(180)
     91      else:
     92          # timeout réduit sur les serveurs clients pour éviter de bloquer le système
     93          socket.setdefaulttimeout(15)
     94  except:
     95      # non implémenté sur python 2.2
     96      pass
     97
     98  if registered:
     99      zephir_proxy = EoleProxy("https://zephir:zephir@"+config.adresse_zephir+":7080", transport=TransportEole())
    100      # pour compatibilité avec des programmes externes
    101      zephir = zephir_proxy
    102
    103 -def convert(objet):
    104      """Transforme les objets unicode contenus dans un objet en chaines
    105      """
    106      if type(objet) == list:
    107          l = []
    108          for item in objet:
    109              l.append(convert(item))
    110          return l
    111      if type(objet) == dict:
    112          dico = {}
    113          for cle in objet.keys():
    114              dico[cle] = convert(objet[cle])
    115          return dico
    116      if type(objet) == unicode:
    117          string =  objet.encode(charset)
    118          return string
    119      return objet
    120
    121 -def u(objet):
    122      if type(objet) == list:
    123          l = []
    124          for item in objet:
    125              l.append(u(item))
    126          return l
    127      if type(objet) == dict:
    128          dico = {}
    129          for cle in objet.keys():
    130              dico[cle] = u(objet[cle])
    131          return dico
    132      if type(objet) == str:
    133          string = unicode(objet, charset)
    134          return string
    135      return objet
    136
    137 -def log(action, etat, msg, date=''):
    138      """fonction de log local et distant (si disponible) des actions zephir effectuées sur le serveur
    139      """
    140      # on insère le log actuel à la liste des logs à envoyer
    141      failed_logs = []
    142      ignored_logs = []
    143      if date == '':
    144          date = str(time.ctime())
    145      liste_logs = [[str(date), action, str(etat), msg]]
    146      # on regarde si il y a des logs différés (erreur de contact avec zephir lors d'un log précédent)
    147      try:
    148          fic_logs = open('%s/deffered_logs' % zephir_dir, 'r')
    149          # rqe : on limite à 20 le nombre d'anciens logs à remonter (pour éviter de bloquer trop longtemps)
    150          deffered_logs = fic_logs.read().strip().split('\n')
    151          if len(deffered_logs) > 20:
    152              old_logs = deffered_logs[:20]
    153              ignored_logs = deffered_logs[20:]
    154          else:
    155              old_logs = deffered_logs
    156          for log in old_logs:
    157              # on stocke ces logs dans la liste
    158              if log.count(';') > 0:
    159                  liste_logs.append(log.split(';'))
    160          fic_logs.close()
    161      except:
    162          # le fichier n'existe pas
    163          # (tous les logs sont passés)
    164          pass
    165
    166      erreur_zephir = 0
    167      # on essaie d'envoyer tous les logs via xmlrpc
    168      for log in liste_logs:
    169          if erreur_zephir == 0:
    170              # on n'essaie pas de réinsérer les logs suivants si il y a eu une erreur
    171              # (évite de répeter les timeouts de la connexion)
    172              try:
    173                  date, action, etat, msg = log
    174                  try:
    175                      msg = u(msg)
    176                  except:
    177                      pass
    178                  if log[0] != '':
    179                      res = zephir_proxy.uucp.log_serveur(config.id_serveur, u(date), u(action), int(etat), msg)
    180                  else:
    181                      res = zephir_proxy.uucp.log_serveur(config.id_serveur, u(str(time.ctime())), u(action), int(etat), msg)
    182                  if res[0] == 0:
    183                      # erreur d'insertion du log, mais zephir répond, on continue en stockant ce log
    184                      failed_logs.append(';'.join(log))
    185              except:
    186                  # echec de la connexion à zephir
    187                  # on stocke les informations de log dans le fichier deffered_logs
    188                  # Ces logs seront parsés au prochain appel de cette fonction
    189                  erreur_zephir = 1
    190                  failed_logs.append(';'.join(log))
    191          else:
    192              failed_logs.append(';'.join(log))
    193
    194      if ignored_logs != []:
    195          failed_logs.extend(ignored_logs)
    196      # on sauvegarde tous les logs non envoyés
    197      try:
    198          fic_logs=open('%s/deffered_logs' % zephir_dir, 'w')
    199          for log in failed_logs:
    200              fic_logs.write(log+'\n')
    201          fic_logs.close()
    202      except:
    203          # pas les droits pour écrire dans le fichier ?
    204          pass
    205
    206      # Le log local est géré par les fonctions Zephir et Zecho
    207      return "ok"
    208
    209  # fonctions de verrouillage
    210
    211  lock_dir = '/var/lock'
    212
    213 -def lock(tags):
    214      """fonction qui crée un ou plusieurs verrous"""
    215      retour = 1
    216      if os.path.isdir(lock_dir):
    217          if not type(tags) == list:
    218              tags = [tags]
    219          for tag in tags:
    220              try:
    221                  fic_temp = open(lock_dir + os.sep + tag, "w").close()
    222              except:
    223                  retour = 0
    224      else:
    225          retour = 0
    226      return retour
    227
    228 -def unlock(tags):
    229      """fonction qui supprime un verrou"""
    230      try:
    231          if not type(tags) == list:
    232              tags = [tags]
    233          for tag in tags:
    234              if os.path.isfile(lock_dir+os.sep+tag):
    235                  os.unlink(lock_dir+os.sep+tag)
    236      except:
    237          return 0
    238      return 1
    239
    240 -def is_locked(tags):
    241      """fonction qui permet de savoir si un verrou particulier est posé"""
    242      if not type(tags) == list:
    243          tags = [tags]
    244      for tag in tags:
    245          if os.path.isfile(lock_dir+os.sep+tag):
    246              return 1
    247      else:
    248          return 0
    249
    250 -def update_conf(id_serveur, adresse_zephir):
    251      """met à jour le fichier conf_zephir"""
    252      template_conf = """#!/usr/bin/env python
    253  id_serveur=%s
    254  adresse_zephir="%s"
    255
    256  if __name__ == "__main__":
    257      print adresse_zephir
    258  """
    259      try:
    260          conf = open(os.path.join(zephir_path, 'zephir_conf/zephir_conf.py'), 'w')
    261          conf.write(template_conf % (str(id_serveur), str(adresse_zephir)))
    262          conf.close()
    263          res = os.system('/bin/chmod 644 %s' % os.path.join(zephir_path, 'zephir_conf/zephir_conf.py'))
    264          assert res == 0
    265      except:
    266          return False
    267      if os.path.isfile(new_addr_file):
    268          os.unlink(new_addr_file)
    269      log('CONFIGURE', 0, """Nouvelle adresse de zephir prise en compte : %s""" % str(adresse_zephir))
    270      return True
    271
    272
    273 -def maj_client_zephir(zephir_proxy, adresse_zephir):
    274      """met à jour le client"""
    275
    276      # on regarde si une mise à jour est nécessaire
    277      # récupération de la version locale
    278      out = os.popen('/usr/bin/dpkg -p zephir-client | grep ^Version')
    279      version_client = out.read().split(':')[1]
    280      out.close()
    281      version_client = "zephir-client_" + version_client.strip()
    282      res_maj = 2
    283      # vérification de la version présente sur zephir
    284      try:
    285          res = convert(zephir_proxy.maj_client(version_client))
    286      except Exception, e:
    287          # fonction de mise à jour non disponible sur cette version de zephir
    288          pass
    289      else:
    290          if res[0] == 0:
    291              print("pas de mise à jour disponible sur zephir")
    292          else:
    293              if res[1] != "OK":
    294                  # une mise à jour est nécessaire
    295                  rpm_client = res[1].encode(charset).strip()
    296                  res_maj = os.system('%s/scripts/maj_client.sh %s %s' % (zephir_dir, adresse_zephir, rpm_client)) / 256
    297      return res_maj
    298
    299 -def update_zephir_ip():
    300      """vérifie si zephir répond sur sa nouvelle adresse (envoyée auparavant via change_ip)
    301      """
    302      # lecture des données stockées (ancienne/nouvelle clé + nouvelle adresse)
    303      ssh_dir = "/var/spool/uucp/.ssh/"
    304      tmp_dir = os.path.join(ssh_dir, 'tmpkeys')
    305      data_new_key = file(new_addr_file).read().strip()
    306      old_key, new_key, new_addr = data_new_key.split('%%')
    307      try:
    308          proxy = EoleProxy("https://zephir:zephir@%s:7080" % (new_addr),transport=TransportEole())
    309          # demande de récupération de la nouvelle clé privée sur zephir. On doit envoyer les clés publiques (actuelle et nouvelle)
    310          code, res = convert(proxy.serveurs.get_key(config.id_serveur, old_key, new_key))
    311          if code == 0:
    312              log('CONFIGURE', 1, """Prise en compte de la nouvelle adresse (%s): clé non reconnue par zephir""" % (new_addr))
    313              return False
    314      except:
    315          return False
    316      fic_priv = os.path.join(tmp_dir, 'new_key')
    317      try:
    318          if os.path.exists(fic_priv):
    319              os.unlink(fic_priv)
    320          os.system('/bin/touch %s;/bin/chmod 600 %s' % (fic_priv, fic_priv))
    321          fichier = file(fic_priv, 'a')
    322          fichier.write(xmlrpclib.base64.decodestring(res))
    323          fichier.close()
    324      except:
    325          print "erreur d'ouverture du fichier %s" %fic_priv
    326          return False
    327      # activation de la clé sur zephir
    328      data = convert(proxy.serveurs.update_key(config.id_serveur))
    329      if data[0] == 0:
    330          print "erreur de mise en place de la nouvelle clé sur zephir : %s" % str(res)
    331          return False
    332      # sauvegarde de la clé actuelle
    333      os.system("/bin/mv %s/id_rsa.pub %s/old_key.pub" % (ssh_dir, tmp_dir))
    334      os.system("/bin/mv %s/id_rsa %s/old_key" % (ssh_dir, tmp_dir))
    335      # mise en place de la nouvelle clé locale
    336      os.system("/bin/mv %s/new_key.pub %s/id_rsa.pub" % (tmp_dir, ssh_dir))
    337      os.system("/bin/mv %s/new_key %s/id_rsa" % (tmp_dir, ssh_dir))
    338      os.system("/bin/chown uucp.uucp %s/id_rsa*" % ssh_dir)
    339      # unlock(['configure', 'uucp', 'maj', 'reconfigure'])
    340      # mise à jour de la configuration uucp
    341      old_addr = config.adresse_zephir
    342      for path_uucp in ['/etc/uucp/port', '/etc/uucp/sys']:
    343          conf_uucp = open(path_uucp).read()
    344          conf_uucp = conf_uucp.replace(old_addr, new_addr)
    345          fic_uucp = open(path_uucp, 'w')
    346          fic_uucp.write(conf_uucp)
    347          fic_uucp.close()
    348      # mise à jour de zephir_conf.py avec la nouvelle adresse
    349      return update_conf(config.id_serveur, new_addr)
    350
    351 -def update_sudoers():
    352      """met à jour la liste des scripts exécutables par sudo en tant que root"""
    353      uucp_pattern = """uucp    ALL=NOPASSWD"""
    354      if os.path.isfile('/etc/sudoers'):
    355          scripts = glob('%s/scripts/*.zephir' % zephir_dir)
    356          scripts.sort()
    357          # liste des scripts disponibles
    358          uucp_conf = ["#ZEPHIR : liste des scripts exécutables par zephir_client, ne pas modifier\n"]
    359          for script in scripts:
    360              uucp_conf.append('%s : %s\n' % (uucp_pattern, script))
    361          uucp_conf.append('#ZEPHIR FIN\n')
    362          # fichier actuel
    363          orig_data = file('/etc/sudoers').readlines()
    364          # supression des lignes concernant uucp
    365          final_data = []
    366          for line in orig_data:
    367              if not (line.startswith(uucp_pattern) or line.startswith('#ZEPHIR')):
    368                  final_data.append(line)
    369          final_data.extend(uucp_conf)
    370          # ré-écriture du fichier
    371          try:
    372              sudo_file = file('/etc/sudoers', 'w')
    373              sudo_file.writelines(final_data)
    374              sudo_file.close()
    375              os.system('chmod 0440 /etc/sudoers')
    376              return True
    377          except:
    378              print "\n! Client Zephir: Le fichier /etc/sudoers n'a pas pu être mis à jour !\n"
    379      return False
    380
    381 -def verif_transfer(zephir_proxy, archive):
    382      """vérifie la validité d'une archive recue et confirme sa réception à zephir"""
    383      verif_archive = convert(zephir_proxy.uucp.get_checksum(config.id_serveur, u(archive)))
    384      if verif_archive[0] == 0:
    385          log('ZEPHIR', 1, 'erreur de récupération du checksum pour '+archive+'.tar')
    386          return verif_archive
    387      else:
    388          md5string = xmlrpclib.base64.decodestring(verif_archive[1])
    389          f_md5 = open(public_dir+os.sep+archive+'.md5', 'w')
    390          f_md5.write(md5string)
    391          f_md5.close()
    392          res = os.system('cd ' + public_dir + ' ; /usr/bin/md5sum -c ' + f_md5.name)
    393          os.unlink(f_md5.name)
    394          if res == 0:
    395              # on informe zephir que le transfert s'est bien passé (rapport ?)
    396              res = convert(zephir_proxy.uucp.confirm_transfer(config.id_serveur, u(archive)))
    397              if res[0] == 1:
    398                  return 1, 'ok'
    399              else:
    400                  #erreur de supression de l'archive sur zephir ?
    401                  return 1, res[1]
    402          else:
    403              # log('WARNING', 'checksum invalide pour '+archive+'.tar')
    404              return 0, 'checksum invalide pour '+archive+'.tar'
    405
    406 -def mod_var_path(filepath):
    407      """change un chemin de fichier pour insérer 'variante' """
    408      filepath = list(os.path.split(filepath))
    409      filepath.insert(1, 'variante')
    410      return os.sep.join(filepath)
    411
    412
    413 -def get_container_file(filepath):
    414      try:
    415          fpath, container = filepath.split('::')
    416          cont_path = container_vars.get('container_path_%s' % container, '')
    417          if cont_path:
    418              return os.path.join(cont_path, fpath.lstrip(os.sep))
    419          else:
    420              return fpath
    421      except:
    422          pass
    423          # pas de container donné (--> container root)
    424      return filepath
    425
    426 -def get_file_perms(base_dir, data_path, variante=False, filepath=""):
    427      """renvoie les informations de permissions associées à un fichier
    428      """
    429      data_dir = base_dir + os.sep + data_path
    430      # lecture des informations sur le fichier si disponibles
    431      if variante == True:
    432          permsfile = base_dir + os.sep + 'droits_variante'
    433      else:
    434          permsfile = base_dir+os.sep+'droits_zephir'
    435      if os.path.isfile(permsfile):
    436          f_rights = file(permsfile)
    437          data = f_rights.read().strip().split('\n')
    438          f_rights.close()
    439      else:
    440          data = []
    441      mode = user = group = ""
    442      recursive = False
    443      if filepath != "":
    444          if variante == True:
    445              result = {mod_var_path(filepath):[mode, user, group, recursive]}
    446          else:
    447              result = {filepath:[mode, user, group, recursive]}
    448      else:
    449          result = {}
    450      for line in data:
    451          if line.startswith(filepath) or filepath == "":
    452              if line.startswith(data_path):
    453                  try:
    454                      filename, mode, user, group, recursive = line.split('#')
    455                      if recursive != '':
    456                          recursive = eval(recursive)
    457                      if variante == True:
    458                          result[mod_var_path(filename)] = [mode, user, group, recursive]
    459                      else:
    460                          result[filename] = [mode, user, group, recursive]
    461                      if filepath != "":
    462                          break
    463                  except:
    464                      # fichier vide ?
    465                      pass
    466      return result
    467
    468 -def sudo_script(cmd, log_prefix='ZEPHIR'):
    469      res = os.system("sudo %s/scripts/%s 2>&1 >> /var/log/zephir/last_action.log" % (zephir_dir, cmd))
    470      if res != 0:
    471          # log de l'erreur sur zephir (par défaut dans la rubrique divers)
    472          log(log_prefix, 1, "Erreur lors de l'exécution du script %s" % cmd)
    473          sys.exit(1)
    474
    475 -def register_log(zephir_proxy, id_serveur, eole_variables, ip_zlog=None, regen=False):
    476      """
    477      mise en place d'un certificat pour envoi des logs centralisés si disponible
    478      @zephir_proxy : objet xmlrpclib.ServeurProxy pour communiquer avec le
    479      Zéphir.
    480      @id_serveur : id du serveur qui s'enregistre
    481      @eole_variables : dictionnaire contenant les chemins des certificats et clé, passés
    482      en argument pour éviter de recharger le dictionnaire
    483      @id_zlog (optionnel) : identifiant du ZéphirLog,  si absent, on considère
    484      que c'est un ZéphirLog qui s'enregistre.
    485      """
    486      id_zlog = None
    487
    488      # Création d'une clé privée si elle n'existe pas
    489      if regen or not os.path.isfile(eole_variables['rsyslog_privkey']):
    490          gen_privkey(eole_variables['rsyslog_privkey'])
    491          # TODO : gérer la révocation
    492      request_data = {}
    493      with open(rsyslog_request_template, 'r') as request_template_data:
    494          request_template = xmlrpclib.base64.encodestring(request_template_data.read())
    495      request_data['template'] = request_template
    496      if ip_zlog != None:
    497          # on considère que c'est un client qui s'enregistre
    498          # recherche du serveur zephirlog correspondant sur zephir
    499          res, managers = zephir_proxy.prelude.get_managers('')
    500          if res != 1:
    501              print_red("Erreur lors de la récupération des serveurs ZéphirLog")
    502              return False
    503          if managers != {}:
    504              id_zephirlog, ip_manager = select_manager(ip_zlog, managers, 'zephirlog')
    505              if id_zephirlog == "":
    506                  print_orange("\nMise en place du certificat ZephirLogs ignoré\n\n")
    507                  return True
    508              else:
    509                  if ip_zlog != ip_manager:
    510                      if not update_logs_conf(ip_manager):
    511                          print_red("""\nL'adresse ip du serveur zephirlog n'a pas pu être sauvegardée\n\n""")
    512                          return False
    513                      print_green("""\nNouvelle adresse ZephirLogs enregistrée dans la configuration : %s\n\n""" % ip_manager)
    514              # mise en place de la CA du serveur ZephirLog sélectionné
    515              request_content = gen_request(rsyslog_request_template,
    516                                          eole_variables['rsyslog_privkey'])
    517              request_content = xmlrpclib.base64.encodestring(request_content)
    518              request_data['request'] = request_content
    519              request_data['rsyslog'] = xmlrpclib.base64.encodestring("$InputTCPServerStreamDriverPermittedPeer {0}".format(eole_variables['serveur']))
    520              res, data = zephir_proxy.prelude.gen_certif(request_data, id_serveur, id_zephirlog)
    521              if res != 1:
    522                  print_red("""\nErreur de récupération des certificats rsyslog sur Zephir.\n\n""")
    523                  return False
    524              with open(eole_variables['rsyslog_ca'], 'w') as rsyslog_ca:
    525                  rsyslog_ca.write(xmlrpclib.base64.decodestring(data['ca_data']))
    526              print_green("\nCertificat racine enregistré sous %s\n\n" % eole_variables['rsyslog_ca'])
    527              with open(eole_variables['rsyslog_cert'], 'w') as rsyslog_crt:
    528                  rsyslog_crt.write(xmlrpclib.base64.decodestring(data['cert_data']))
    529              print_green("\nCertificat rsyslog enregistré sous %s\n\n" % eole_variables['rsyslog_cert'])
    530              if data.has_key('rsyslog_data'):
    531                  outgoing_dir = '/etc/rsyslog.d/outgoing_peers'
    532                  if not os.path.exists(outgoing_dir):
    533                      os.makedirs(outgoing_dir)
    534                  with open(os.path.join(outgoing_dir, 'tls.peers'), 'w') as rsyslog_conf:
    535                      rsyslog_conf.write(xmlrpclib.base64.decodestring(data['rsyslog_data']))
    536      else:
    537          # on considère que c'est un ZéphirLog qui s'enregistre
    538          request_content = gen_request(rsyslog_request_template,
    539                  eole_variables['rsyslog_privkey'])
    540          request_data['request'] = xmlrpclib.base64.encodestring(request_content)
    541          request_data['rsyslog'] = xmlrpclib.base64.encodestring("$ActionSendStreamDriverPermittedPeer {0}".format(eole_variables['serveur']))
    542          res, data = zephir_proxy.prelude.gen_certif(request_data, id_serveur)
    543          with open(eole_variables['rsyslog_ca'], 'w') as rsyslog_ca:
    544              rsyslog_ca.write(xmlrpclib.base64.decodestring(data['ca_data']))
    545          print_green("\nCertificat racine enregistré sous %s\n\n" % eole_variables['rsyslog_ca'])
    546          with open(eole_variables['rsyslog_cert'], 'w') as rsyslog_crt:
    547              rsyslog_crt.write(xmlrpclib.base64.decodestring(data['cert_data']))
    548          print_green("\nCertificat rsyslog enregistré sous %s\n\n" % eole_variables['rsyslog_cert'])
    549          if data.has_key('rsyslog_data'):
    550              incoming_dir = '/etc/rsyslog.d/incoming_peers'
    551              if not os.path.exists(incoming_dir):
    552                  os.makedirs(incoming_dir)
    553              with open(os.path.join(incoming_dir, 'tls.peers'), 'w') as rsyslog_conf:
    554                  rsyslog_conf.write(xmlrpclib.base64.decodestring(data['rsyslog_data']))
    555      return True
    556
    557
    558 -def wait_for_port(addr, port, timeout = 20):
    559      """attend qu'une connexion soit disponible sur une adresse/port
    560      timeout : temps d'attente maximum avant d'abandonner (en secondes)
    561      """
    562      sock_timeout = 3
    563      run_time = 0
    564      while run_time < timeout:
    565          sock_test = socket.socket()
    566          sock_test.settimeout(sock_timeout)
    567          try:
    568              sock_test.connect((addr, port))
    569              return True
    570          except socket.timeout:
    571              pass
    572          except socket.error:
    573              time.sleep(sock_timeout)
    574          run_time += sock_timeout
    575      return False
    576
    577 -def check_prelude_conf():
    578      """récupère les options prelude définies dans la configuration creole
    579      """
    580      ip_conf = ''
    581      sondes = []
    582      try:
    583          # si une adresse_ip est définie, on la propose par défaut
    584          conf = EoleDict()
    585          conf.read_dir(eoledirs)
    586          conf.load_values('/etc/eole/config.eol')
    587          try:
    588              ip_conf = conf.get_value('adresse_ip_prelude_manager')[0]
    589          except IndexError:
    590              ip_conf = ""
    591          if eole_module == 'zephirlogs':
    592              print "** enregistrement prelude-lml"
    593              sondes = ['prelude-lml']
    594          else:
    595              for varname, var in conf.variables.items():
    596                  if varname.startswith('sonde_') and var.get_final_value() == 'oui':
    597                      sondes.append(varname.replace('sonde_', '').replace('__', '-'))
    598                      print "** enregistrement ", varname.replace('sonde_', '').replace('__', '-')
    599      except:
    600          traceback.print_exc()
    601          pass
    602      return ip_conf, sondes
    603
    604 -def select_manager(ip_conf, managers, mgr_type = 'preludemanager'):
    605      """propose le choix du  manager sur lequel l'enregistrement doit s'effectuer
    606      """
    607      # choix du manager
    608      saisie_default = ""
    609      choix = [""]
    610      id_man = ""
    611      ip_manager = ""
    612      if ip_conf is not None:
    613          ip_manager = ip_conf
    614          # ip du manager donnée en paramètre, on recherche l'id correspondant
    615          for id_manager, data_man in managers.items():
    616              ip_man = data_man[0]
    617              libelle = data_man[1]
    618              if ip_man == ip_conf:
    619                  id_man = id_manager
    620      if id_man == "":
    621          if ip_conf:
    622              print_orange("\nLe serveur %s correspondant à l'ip %s n'a pas été trouvé." % (mgr_type, ip_conf))
    623          print "\nserveurs %s disponibles :\n" % mgr_type
    624          id_default = ""
    625          # si pas de manager spécifié, on propose un choix
    626          for id_man in managers.keys():
    627              ip_man = managers[id_man][0]
    628              libelle = managers[id_man][1]
    629              choix.append(id_man)
    630              print id_man, " -> ", ip_man, "(", libelle, ")"
    631          id_man = "undef"
    632          while id_man not in choix:
    633              id_man = raw_input("\nIdentifiant du serveur %s à utiliser (rien pour ignorer) ? " % (mgr_type))
    634          if id_man != "":
    635              ip_manager = managers[id_man][0]
    636      return id_man, ip_manager
    637
    638 -def update_prelude_conf(ip_manager):
    639      """met à jour la configuration creole du serveur et instancie les templates
    640      nécessaires à l'enregistrement des sondes prelude
    641      """
    642      # mise en place de la configuration
    643      conf = EoleDict()
    644      conf.read(os.path.join(eoleroot, 'dicos', '1_prelude.xml'))
    645      prelude_files = conf.files
    646      prelude_filelists = conf.filelists
    647      # instanciation des fichier de configuration prelude
    648      conf = EoleDict()
    649      # on récupère les autres variables
    650      conf.read_dir(eoledirs)
    651      # on lit la configuration dans config.eol (ou zephir.eol si non instancié)
    652      if os.path.isfile('/etc/eole/config.eol'):
    653          conf.load_values('/etc/eole/config.eol')
    654      else:
    655          conf.load_values('/root/zephir.eol')
    656      conf.set_value('adresse_ip_prelude_manager' , ip_manager)
    657      saved = True
    658      for conf_file in ['/etc/eole/config.eol', '/root/zephir.eol']:
    659          if os.path.isfile(conf_file):
    660              if not conf.save_values(conf_file):
    661                  saved = False
    662      if saved:
    663          # et on ne garde que les fichiers prelude
    664          conf.files = prelude_files
    665          conf.filelists = prelude_filelists
    666          # instanciation des fichiers templates avec les valeurs chargées
    667          try:
    668              conf.instance()
    669          except:
    670              traceback.print_exc()
    671              print '\n!! erreur de génération de la configuration prelude !!\n'
    672              saved = False
    673      return saved
    674
    675 -def update_logs_conf(ip_manager):
    676      """met à jour la configuration creole du serveur
    677      """
    678      # mise en place de la configuration
    679      try:
    680          conf = EoleDict()
    681          conf.read(os.path.join(eoleroot, 'dicos', '1_logs.xml'))
    682          # instanciation des fichier de configuration prelude
    683          conf = EoleDict()
    684          # on récupère les autres variables
    685          conf.read_dir(eoledirs)
    686          # on lit la configuration dans config.eol (ou zephir.eol si non instancié)
    687          if os.path.isfile('/etc/eole/config.eol'):
    688              conf.load_values('/etc/eole/config.eol')
    689          else:
    690              conf.load_values('/root/zephir.eol')
    691      except:
    692          print "Erreur à la lecture de la configuration du serveur"
    693          return False
    694      conf.set_value('adresse_ip_serveur_logs' , ip_manager)
    695      saved = True
    696      for conf_file in ['/etc/eole/config.eol', '/root/zephir.eol']:
    697          if os.path.isfile(conf_file):
    698              if not conf.save_values(conf_file):
    699                  saved = False
    700      return saved
    701
    702 -def register_sonde(sonde, id_man, ip_manager, zephir_proxy):
    703      retry = True
    704      num_tries = 0
    705      while retry:
    706          retry = False
    707          # lancement du serveur d'enregistrement à distance
    708          code, pass_register = convert(zephir_proxy.prelude.register_server(id_man))
    709          if code == -1:
    710              # si le serveur est déjà occupé, on attend au maximum 30 secondes (essai toutes les 5 secondes)
    711              print "Un enregistrement est déjà en cours sur prelude-manager. nouvelle tentative dans 5 secondes..."
    712              if num_tries < 6:
    713                  num_tries += 1
    714                  retry = True
    715                  time.sleep(4)
    716                  continue
    717              else:
    718                  return False
    719          elif code == 0:
    720              return False
    721          # attente de la dispo du serveur
    722          print "Attente du lancement du serveur d'enregistrement sur prelude-manager"
    723          conn_ok = wait_for_port(ip_manager, 5553)
    724          # lancer adduser avec les paramêtres donnés
    725          if conn_ok:
    726              print " - enregistrement de la sonde %s" % sonde
    727              options = get_options(zephir_dir)
    728              if sonde in options:
    729                  permissions, uid, gid, services = options[sonde]
    730              else:
    731                  permissions = "idmef:w admin:r"
    732                  uid = "root"
    733                  gid = "root"
    734                  services = [sonde]
    735              cmd_register = '/usr/bin/prelude-admin register %s "%s" %s --uid %s --gid %s --passwd=%s 2>/dev/null' % (sonde, permissions, ip_manager, uid, gid, pass_register)
    736              res = os.system(cmd_register)
    737              if res != 0:
    738                  print "\terreur lors de l'enregistrement de %s \n\t(%s)" % (sonde, cmd_register)
    739              else:
    740                  pass
    741                  res = os.system('/bin/chown %s.%s /etc/prelude/profile/%s/analyzerid' % (uid, gid, sonde))
    742                  for serv in services:
    743                      print " - relance du service %s ..." % serv
    744                      service_out(serv, 'restart')
    745          else:
    746              print "\nserveur d'enregistrement non lancé ?"
    747              return False
    748      return True
    749
    750 -def register_prelude(zephir_proxy):
    751      """mise en place de la configuration prelude si nécessaire"""
    752      # recherche des managers disponibles
    753      try:
    754          ret_code, managers = convert(zephir_proxy.prelude.get_managers())
    755      except xmlrpclib.ProtocolError:
    756          print("Vous n'êtes pas autorisé à utiliser les fonctionnalités prelude")
    757          return False
    758      except:
    759          print "\n!! erreur de lecture de la configuration prelude sur zephir"
    760          return False
    761      if managers != {}:
    762          ip_conf, sondes = check_prelude_conf()
    763          id_man, ip_manager = select_manager(ip_conf, managers)
    764          if id_man == "":
    765              print_orange("\nEnregistrement auprès du serveur PreludeManager ignoré\n\n")
    766          else:
    767              if ip_manager != ip_conf:
    768                  if not update_prelude_conf(ip_manager):
    769                      print_red("""\nL'adresse ip du serveur PreludeManager n'a pas pu être sauvegardée\n\n""")
    770                      return False
    771                  else:
    772                      print_green("""\nNouvelle adresse PreludeManager enregistrée dans la configuration : %s\n\n""" % ip_manager)
    773              # pour chaque sonde définie dans la configuration, on effectue un enregistrement (prelude-adduser)
    774              err_sonde = False
    775              for sonde in sondes:
    776                  if not register_sonde(sonde, id_man, ip_manager, zephir_proxy):
    777                      err_sonde = True
    778                      print_red ("\n Echec de l'enregistrement de la sonde %s sur le serveur Preludemanager (%s) \n\n" % (sonde, ip_manager))
    779              if err_sonde:
    780                  return False
    781      return True
    782
    783 -def saisie(variable,message):
    784      """effectue la saisie d'une variable en utilisant
    785      une valeur par défaut si disponible
    786      """
    787      try:
    788          val_def = " (%s par défaut)" % defaults[variable]
    789      except Exception,e:
    790          val_def = ""
    791      val = raw_input(message + val_def + " : ")
    792      if val == "" and val_def != "":
    793          return defaults[variable]
    794      else:
    795          return val
    796
    797  pppoe_int_template = """# zephir_client : template minimum pour montage d'une connexion pppoe
    798  # loopback network interface
    799  auto lo
    800  iface lo inet loopback
    801
    802  # dsl provider
    803  auto dsl-provider
    804  iface dsl-provider inet ppp
    805  pre-up /sbin/ifconfig %%pppoe_interface up
    806  provider dsl-provider
    807
    808  auto %%pppoe_interface
    809  iface %%pppoe_interface inet manual
    810  """
    811
    812  dsl_provider_template = """
    813  # Minimalistic default options file for DSL/PPPoE connections
    814
    815  noipdefault
    816  defaultroute
    817  replacedefaultroute
    818  hide-password
    819  noauth
    820  persist
    821  updetach
    822  usepeerdns
    823  user "%%pppoe_user"
    824  """
    825
    826 -def conf_network(use_pppoe=False):
    827
    828      def configure_dns(ip_dns):
    829          """
    830          Vérification et configuration du serveur DNS
    831          """
    832          testdns = (['/usr/bin/host', '-W2', '-tA', 'bp-eole.ac-dijon.fr', ip_dns])
    833          res = system_out(testdns)
    834          if res[0] != 0:
    835              print "le serveur DNS %s ne répond pas (%s)" % (ip_dns, res[1])
    836              return False
    837          server_conf = "nameserver %s" % ip_dns
    838          f_dns = open('/etc/resolv.conf', 'w')
    839          f_dns.write(server_conf)
    840          f_dns.close()
    841          return True
    842
    843      # création d'une configuration réseau minimum
    844      if not use_pppoe:
    845          # connexion ethernet classique
    846          ip_eth0 = mask_eth0 = gateway = ""
    847          while ip_eth0 =="" or mask_eth0 == "" or gateway == "":
    848              interf = saisie("interf","interface connectée sur l'extérieur")
    849              ip_eth0 = saisie("ip_eth0","adresse_ip %s" % interf)
    850              mask_eth0 = saisie("mask_eth0","masque de réseau pour %s" % interf)
    851              gateway = saisie("gateway","adresse de la passerelle")
    852          system_code(['/sbin/ifconfig', interf, ip_eth0, 'netmask', mask_eth0])
    853          system_code(['/sbin/route', 'add', 'default', 'gw', gateway, 'dev', interf])
    854          system_code(['/sbin/ifconfig', interf, 'up'])
    855          dns_ok = False
    856          while not dns_ok:
    857              ip_dns = saisie("ip_dns", "adresse du serveur DNS (ou rien)")
    858              if ip_dns == "" or configure_dns(ip_dns):
    859                  dns_ok = True
    860      else:
    861          if not eole_module.startswith("amon"):
    862              exit_err("""La connexion par pppoe n'est gérée que sur les modules amon et amonecole""")
    863          configs = {'pap-secrets':'/etc/ppp','chap-secrets':'/etc/ppp', 'dsl-provider':'/etc/ppp/peers'}
    864          for tmpl in configs.keys():
    865              if not os.path.isfile(os.path.join(distrib_dir, tmpl)):
    866                  exit_err("""Fichier de configuration non présent : %s""" % tmpl)
    867          interf_ppp = login_ppp = pass_ppp = mtu_ppp = ""
    868          while interf_ppp == "" or login_ppp == "" or pass_ppp == "":
    869              # connexion pppoe - saisie login/pwd et interface
    870              interf_ppp = saisie("interf","interface utilisée pour la connexion pppoe")
    871              mtu_ppp = saisie("mtu_ppp","MTU utilisé pour la connexion pppoe (facultatif)")
    872              login_ppp = saisie("login_ppp", "utilisateur pour la connexion pppoe")
    873              pass_ppp = getpass.getpass("mot de passe pour la connexion pppoe : ")
    874          # mise en place des fichiers de configuration : pap(/chap)-secrets et dsl-provider
    875          try:
    876              for tmpl_name, dest_dir in configs.items():
    877                  if tmpl_name == 'dsl-provider':
    878                      conf_data = dsl_provider_template
    879                      # gestion du MTU pour dls-provider
    880                      if mtu_ppp == "":
    881                          conf_data += 'pty "pppoe -I %s -T 80"' % (interf_ppp)
    882                      else:
    883                          conf_data += 'pty "pppoe -I %s -T 80 -m %s"' % (interf_ppp, mtu_ppp)
    884                  else:
    885                      tmpl = os.path.join(distrib_dir, tmpl_name)
    886                      conf_data = open(tmpl).read()
    887                  # remplacement des variables
    888                  conf_data = conf_data.replace("%%pppoe_user", login_ppp)
    889                  conf_data = conf_data.replace("%%pppoe_passwd", pass_ppp)
    890                  conf_data = conf_data.replace("%%pppoe_interface", interf_ppp)
    891                  # écriture du résultat dans sa destination
    892                  f_conf = open(os.path.join(dest_dir, tmpl_name), 'w')
    893                  f_conf.write(conf_data)
    894                  f_conf.close()
    895              # fichier interfaces minimum
    896              tmpl_name = "interfaces"
    897              f_int = open('/etc/network/interfaces', 'w')
    898              f_int.write(pppoe_int_template.replace("%%pppoe_interface", interf_ppp))
    899              f_int.close()
    900          except:
    901              exit_err("erreur de mise en place du fichier %s" % tmpl_name)
    902          # lancement de la connexion ppp
    903          print_orange("""\nRelance des services réseaux ...\n""")
    904          if not service_code('networking', 'restart') == 0:
    905              print_red("""Erreur au redémarrage du réseau""")
    906
    907 -def exit_err(msg):
    908      print_red("\n\n%s\n\n" % msg)
    909      sys.exit(1)
    910