X-Git-Url: http://gitweb.pimeys.fr/?a=blobdiff_plain;f=ssh%2Fgenerate_config.py;fp=ssh%2Fgenerate_config.py;h=d71b488196017881ebcdd37e8cf69a3e31c7d3af;hb=5adc8d9819f83e3e0e8a97797d5fad23a5bc61a0;hp=0000000000000000000000000000000000000000;hpb=c73ee4619165a69d0bb7ffab40cac22c25f917ee;p=scripts-20-100.git diff --git a/ssh/generate_config.py b/ssh/generate_config.py new file mode 100755 index 0000000..d71b488 --- /dev/null +++ b/ssh/generate_config.py @@ -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")