]> gitweb.pimeys.fr Git - scripts-20-100.git/blobdiff - ssh/generate_config.py
Génération automatique de .ssh/config
[scripts-20-100.git] / ssh / generate_config.py
diff --git a/ssh/generate_config.py b/ssh/generate_config.py
new file mode 100755 (executable)
index 0000000..d71b488
--- /dev/null
@@ -0,0 +1,155 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""Script de génération automatique de fichier ~/.ssh/config
+
+TODO : mettre une option pour append le ssh des bornes
+"""
+
+import sys
+import re
+sys.path.append('/usr/scripts/')
+
+import lc_ldap.shortcuts
+import lc_ldap.objets
+
+#: Fichier à inclure au début
+static_before_file = "./static_before"
+
+#: Fichier à inclure à la fin
+static_after_file = "./static_after"
+
+#: regexp pour exclure certains "serveurs"
+black_regex = re.compile('^((bigbrother|hugebrother|littlebrother|tinybrother|imprimante|vigile(--?\d[a-z])?|bat[abcghijmopk]-\d|minigiga|multiprise-v6|chu|pika|kvm|pulsar|nols2?).adm.crans.org|ftp.federez.net|ns1.crans.ens-cachan.fr)$')
+
+#: Proxy pour contacter le VLAN adm
+adm_proxy = u"sable.crans.org"
+
+#: Login pour se connecter sur les serveurs Cr@ns
+login_crans = u"legallic"
+
+#: À afficher avant les serveurs Cr@ns
+crans_header = u"""
+# +-------------------+
+# | Serveurs du Cr@ns |
+# +-------------------+
+# Accessible aux apprentis
+# sauf zamok et ssh2, accessibles à tous les adhérents
+
+"""
+
+#: À afficher avant les serveurs adm
+crans_adm_header = u"""
+# +-------------------------+
+# | Serveurs Cr@ns adm-only |
+# +-------------------------+
+# Accessibles aux apprentis, mais ne sont que sur le VLAN adm
+# d'où la ProxyCommand
+# fy et fz ne sont accessibles qu'aux nounous
+
+"""
+
+def blacklisted(key, aliases):
+    """Répond True si le serveur ne doit pas apparaître dans le fichier de conf."""
+    for a in aliases:
+        if black_regex.match(a):
+            return True
+    return False
+
+def cache_servers(servs):
+    import json
+    json.dump(servs, open("plouf.json", "w"))
+
+def load_servers():
+    import json
+    return json.load(open("plouf.json"))
+
+def get_servers(help=None):
+    """Récupère la liste des serveurs dans la base LDAP."""
+    if help is None:
+        c = lc_ldap.shortcuts.lc_ldap_readonly(user=u"legallic")
+        
+        l = c.allMachines()
+        l = [m for m in l if isinstance(m, lc_ldap.objets.machineCrans)]
+    else:
+        l = help
+    
+    hosts = {}
+    for m in l:
+        host = m["host"][0].value
+        h = host.replace(".crans.org", "")
+        if hosts.has_key(h):
+            print (u"Doublon : clé %s had %r and wants %r" % (h, hosts[h], [host] + [a.value for a in m["hostAlias"]])).encode("utf-8")
+        else:
+            hosts[h] = [host] + [a.value for a in m["hostAlias"]]
+    return hosts
+
+def output(key, aliases, use_adm_proxy=False):
+    """ Renvoie le block de conf pour un host.
+        Traite particulièrment : ssh2, les ilo, la ferme"""
+    # On teste si le serveur est dans la ferme
+    ferme = any([a.endswith(u".ferme.crans.org") for a in aliases])
+    shorts = list(set([a.replace(".crans.org", "") for a in aliases]))
+    if ferme:
+        shorts.append(a.split(".", 1)[0])
+    shorts.sort()
+    if key in shorts:
+        shorts.remove(key)
+    out = u"Host %s\n" % (u" ".join([key] + shorts + aliases))
+    if key=="ssh2":
+        out += u"    # Un serveur ssh qui n'est qu'un nat vers 138.231.136.1:22\n"
+        out += u"    # pour passer à travers les blocages de ports (443 = https)\n"
+        out += u"    HostName 138.231.136.2\n"
+        out += u"    Port 443\n"
+        out += u"    User %s\n" % login_crans
+        out += u"    ForwardAgent yes\n"
+        out += u"\n"
+        return out
+    hostname = u"%s.crans.org" % (key)
+    out += u"    HostName %s\n" % (hostname)
+    out += u"    User %s\n" % login_crans
+    if not key in ["apprentis", "batk-0"]:
+        out += u"    ForwardAgent yes\n"
+    if use_adm_proxy:
+        out += u"    ProxyCommand ssh %s -W %%h:%%p\n" % (adm_proxy)
+    if key.endswith("-ilo.adm"):
+        out += u"    HostKeyAlgorithms ssh-rsa\n"
+    out += u"\n"
+    return out
+
+def compute_ssh_config(servers):
+    """Affiche le ssh_config à partir de la liste de serveurs."""
+    # Un serveur "plouf.adm.crans.org" est adm-only si aucune clé "plouf", "plouf.ferme" n'existe
+    keys = servers.keys()
+    adm_only = {k : aliases for k, aliases in servers.items() if all([not k.replace(".adm", zone) in keys
+                                                                      for zone in [".ferme", ""]])}
+    # On veut pouvoir utiliser babar et pas seulement babar.adm
+    for k in adm_only.keys():
+        newk = k.replace(".adm", "")
+        if not newk in adm_only[k]:
+            adm_only[k] = [k.replace(".adm", "")] + adm_only[k]
+    for a in adm_only.keys():
+        del servers[a]
+    s = crans_header
+    keys = servers.keys()
+    keys.sort()
+    for h in keys:
+        s += output(h, servers[h])
+    s += crans_adm_header
+    keys = adm_only.keys()
+    keys.sort()
+    for h in keys:
+        s += output(h, adm_only[h], use_adm_proxy=True)
+    return s
+
+if __name__ == '__main__':
+    try:
+        servers = load_servers()
+    except:
+        servers = get_servers()
+    cache_servers(servers)
+    servers = {h:aliases for h, aliases in servers.iteritems() if not blacklisted(h, aliases)}
+    out = compute_ssh_config(servers)
+    before = open(static_before_file).read().decode("utf-8")
+    after = open(static_after_file).read().decode("utf-8")
+    print (before + out + after).encode("utf-8")