Outils pour utilisateurs

Outils du site


python:acn-py-installer

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
Prochaine révisionLes deux révisions suivantes
python:acn-py-installer [2020/01/26 16:03] – [Lien] crustpython:acn-py-installer [2020/02/09 00:38] – [Configuration, côté client] crust
Ligne 1: Ligne 1:
-====== Serveur de cache APT ======+====== Serveur de cache APT  / cron-apt ======
  
  
-Script d'auto configuration d'un serveur de cache pour APT, côté serveur et client.+Script d'auto configuration d'un **serveur de cache pour APT, côté serveur et client**. 
 +Installation d'un **cron-apt récupérant les mises  à jour la nuit** et **installant automatiquement les mises à jour de sécurité** des repo. présentes sur votre système. 
 +Gestion de la configuration aussi bien niveau **installation client / serveur**. 
 + 
 +Ce script peut être installé via un compte **root**  (base debian) mais également via  **sudo** (base ubuntu, mint...). Il est écrit en **python3** et doit être lancé avec les droits administrateur. 
 + 
 +Utilité dans le cadre de la gestion d'un parc de PC. Un PC est défini comme **serveur** et sera le seul à utiliser la bande passante de l'Internet pour récupérer les mises à jour. **Les clients** se connectent, eux, via ce PC uniquement pour **apt** et donc utilisent le réseau local. **Le parc de client** peut être **hétérogène** (au niveau de la distribution mais aussi de leurs versions : Debian Stable / SID / Mint / Lubuntu / Mandriva ...) du moment qu'ils utilisent **des paquets au format Debian (.deb)**. 
 + 
 +La mise à jour du cache se fera depuis le serveur, mais également dès l'accès à ce serveur par un client.
  
 // //
Ligne 9: Ligne 17:
 Le principe est qu'une machine centrale héberge le mandataire pour un réseau local. Les clients règlent leur configuration d'APT pour télécharger sur cette machine. Apt-Cacher NG conserve une copie de toutes les données utiles transitant à travers lui et, quand une requête similaire est faite, la copie en cache des données est délivrée sans être téléchargée à nouveau.//  Le principe est qu'une machine centrale héberge le mandataire pour un réseau local. Les clients règlent leur configuration d'APT pour télécharger sur cette machine. Apt-Cacher NG conserve une copie de toutes les données utiles transitant à travers lui et, quand une requête similaire est faite, la copie en cache des données est délivrée sans être téléchargée à nouveau.// 
  
-Ci dessus la version 0.1.0+{{ :python:apt-cacher-server.png?direct&400 |}} 
 + 
 + 
 +===== Les avantages d'APT-CACHER-NG ===== 
 + 
 + 
 +    * apt-cacher-ng est un gain de temps 
 +    * apt-cacher-ng limite l'utilisation de la bande passante 
 +    * apt-cacher-ng permet d'intégrer des images ISO (DVD) et des importations de cache apt 
 + 
 +===== Configurations du script ===== 
 + 
 +  * Configuration, côté serveur 
 + 
 +==== Installation du paquet : ==== 
 + 
 +  * apt-cacher-ng 
 +  * cron-apt 
 + 
 + 
 +==== Configuration, côté client ==== 
 + 
  
-Mais préfèrable de suivre la version du GIT : https://github.com/CyrilleBiot/scripts/blob/master/acn.py+===== Le script ===== 
 +Ci dessus la version 2.0.0
  
 +Mais préfèrable de suivre la version du GIT : [[https://github.com/CyrilleBiot/scripts/|https://github.com/CyrilleBiot/scripts/]]
 <code bash>#!/usr/bin/env python <code bash>#!/usr/bin/env python
 # -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
Ligne 19: Ligne 51:
     apt-cacher-ng soit en tant que serveur (ajout du paquet sur le système     apt-cacher-ng soit en tant que serveur (ajout du paquet sur le système
     soit en tant que client (cration d'un fichier de proxy apt)     soit en tant que client (cration d'un fichier de proxy apt)
 +    Possibilité pour les clients de choisir le port d'écoute du serveur
 +    Installation de cron-apt avec configuration spécifique
 +    pour installation automatique des mises à jour de sécurité des repo
 +    présents sur le système
 """ """
  
Ligne 25: Ligne 61:
 __credits__ = "Cyrille BIOT" __credits__ = "Cyrille BIOT"
 __license__ = "GPL" __license__ = "GPL"
-__version__ = "0.1.2+__version__ = "2.0.0
-__date__ = "2020/01/26"+__date__ = "2020/02/05"
 __maintainer__ = "Cyrille BIOT" __maintainer__ = "Cyrille BIOT"
 __email__ = "cyrille@cbiot.fr" __email__ = "cyrille@cbiot.fr"
 __status__ = "Devel" __status__ = "Devel"
  
-import os, re, sys +import os, re, sys, platform 
-import platform, subprocess, socket+import nmap, subprocess, socket 
 + 
  
  
 def baseDebian(): def baseDebian():
-    """ Fonction permettant de connaitre le Systeme d'exploitant faisant tourner le script +    """ 
-        Ou DEBIAN ou UBUNTU pour savoir si on utilise su ou sudo +    Fonction permettant de connaitre le Systeme d'exploitant faisant tourner le script 
-        Retourne une variable de type string (admin)+    Ou DEBIAN ou UBUNTU pour savoir si on utilise su ou sudo 
 +    Retourne une variable de type string (admin
 +    :return: admin soit 'debian' (root), soit 'ubuntu' (sudo)
     """     """
     # Ubuntu ou DEBIAN     # Ubuntu ou DEBIAN
     if 'Debian' in platform.version():     if 'Debian' in platform.version():
         # Si DEBIAN, verif si root lance le script         # Si DEBIAN, verif si root lance le script
-        admin = 'su' +        print('Vous utilisez un système Debian (su pour administration).')
-        print('Vous utilisez un système Debian (su pour adminstration).')+
         if not os.geteuid() == 0:         if not os.geteuid() == 0:
-            sys.exit("Seul le root peut lancer ce script. Nécessite privilèges administrateur")+            sys.exit("Seul le root peut lancer ce script. Nécessite privilèges administrateur.") 
 +        distrib = 'debian'
     else:     else:
-        print('Vous utilisez un système non Debian (sudo pour adminstration).') +        if not os.geteuid() == 0: 
-        admin = 'sudo+            print("Ce programme requiert un lancement via 'sudo'"
-    return admin+            sys.exit("Ce programme doit être lancé avec les droits administrateur.\nUtiliser sudo LeScript.py"
 +        print('Vous utilisez un système non Debian (sudo pour administration).') 
 +        distrib = 'ubuntu
 +    return distrib
  
- +def installPackage(package, debianUbuntu): 
-def installServeur(): +    """ 
-    """ Fonction installant le serveur de cache apt-cacher-ng """ +    Fonction installant un package debian ou ubuntu 
-    portACN = 3142 +    :param package: le nom du paquet à installer 
-    ipServeur = ipRecuperation() +    :param debianUbuntu: soit 'debian' / soit 'ubuntu' 
- +    :return: None 
-    # Installation SERVEUR +    """ 
-    # Tester si le package apt-cacher-ng est installé ou non +    retval = subprocess.call(['which'package])
-    retval = subprocess.call(["which""apt-cacher-ng"])+
     if retval != 0:     if retval != 0:
-        print("Le package apt-cacher-ng n'est pas intallé. Installation...")+        print("Le package {} n'est pas intallé. Installation...".format(package))
  
         # Paramètres de l'install         # Paramètres de l'install
-        cmdInstall = ['apt-get', 'install', 'apt-cacher-ng', '-y']+        cmdInstall = ['apt-get', 'install', package, '-y']
         cmdUpdate = ['apt-get', 'update']         cmdUpdate = ['apt-get', 'update']
-        # Debian, Ubuntu 
-        admin = baseDebian() 
  
         # Adaptation système Ubuntu         # Adaptation système Ubuntu
-        if admin == 'sudo':+        if debianUbuntu == 'ubuntu':
             cmdInstall.insert(0, 'sudo')             cmdInstall.insert(0, 'sudo')
             cmdUpdate.insert(0, 'sudo')             cmdUpdate.insert(0, 'sudo')
Ligne 77: Ligne 117:
         # On installe le paquet         # On installe le paquet
         subprocess.run(cmdInstall)         subprocess.run(cmdInstall)
-        subprocess.run(cmdUpdate)+        #subprocess.run(cmdUpdate)
     else:     else:
-        print('Le package apt-cacher-ng est déjà présent sur votre système.'+        print('Le package {} est déjà présent sur votre système.'.format(package)
-        sys.exit()+ 
 +    return None 
 + 
 +def installServeur(ip, port,distrib): 
 +    """ 
 +    Fonction installant le serveur de cache apt-cacher-ng 
 +    :param ip: IP du Serveur 
 +    :param port: interger port ACN 
 +    :param distrib: Ubuntu ou Debian 
 +    :return: None 
 +    """ 
 + 
 +    # Installation du serveur 
 +    installPackage('apt-cacher-ng',distrib)
  
     # Affichage Informations     # Affichage Informations
     print("===============================================")     print("===============================================")
     print("Le serveur de cache est dès lors opérationnel")     print("Le serveur de cache est dès lors opérationnel")
-    print("Le port d'écoute est : {}".format(portACN)) +    print("Le port d'écoute est : {}".format(port)) 
-    print("Page d'aministration : http://{}:{}/acng-report.html".format(ipServeurportACN))+    print("Page d'aministration : http://{}:{}/acng-report.html".format(ipport))
     print("Notez bien l'ip de votre serveur, elle vous sera indispensable pour la configuration des clients.")     print("Notez bien l'ip de votre serveur, elle vous sera indispensable pour la configuration des clients.")
-    print("L'IP du serveur est : {} ".format(ipServeur))+    print("L'IP du serveur est : {} ".format(ip))
     print("Indispensable : cette IP doit être FIXE (réglage sur votre BOX ou serveur DHCP).")     print("Indispensable : cette IP doit être FIXE (réglage sur votre BOX ou serveur DHCP).")
 +    print("Cette machine est un serveur, mettre de ne l'arrêter. Les mises à jour s'effectuant la nuit.")
  
 +    return None
  
-def installClient(ip): + 
-    """ Fonction installant un fichier de configuration apt pour les postes clients +def installClient(ipServeur,portACN):
-        Créer un fichier dans /etc/apt/apt.conf.d/ ayant pour nom 00aptproxyANC+
     """     """
-    print("Installation client.") +    Fonction installant un fichier de configuration apt pour les postes clients 
-    # Reste à insérer l'ip et à le coller au bo n endroit +    Créer un fichier dans /etc/apt/apt.conf.d/ ayant pour nom 00aptproxyANC 
-    msgApt = 'Acquire::http::Proxy "'ip + ':3142";\n'+    :param ipServeur:  ip du serveur ACN 
 +    :param portACN: port d'écoute du serveur ACN 
 +    :return: None 
 +    """ 
 + 
 +    # COnfig IP serveur dans un fichier de proxy APT 
 +    msgApt = 'Acquire::http::Proxy "http://' + ipServeur + ':' + str(portACN) + '";\n' 
 +    print(msgApt)
     dirInstall = '/etc/apt/apt.conf.d/'     dirInstall = '/etc/apt/apt.conf.d/'
     fileName = '00aptproxyANC'     fileName = '00aptproxyANC'
Ligne 105: Ligne 166:
     fichier.write(msgApt)     fichier.write(msgApt)
     fichier.close()     fichier.close()
 +    return None
  
 +
 +
 +def portSelection(portACN):
 +    while True:
 +        try:
 +            portDefault = input("Utiliser le port par défaut 3142 (recommandé) ?. [Oui / Non]  ")
 +            if portDefault.lower() == 'oui':
 +                print('Port Serveur {}'.format(portACN))
 +                break
 +
 +            elif portDefault.lower() == 'non':
 +                try:
 +                    portSelect = int(input("Saisir le port du serveur Apt-Cacher-Ng. Entre 0 et 65 535. : "))
 +                    if -1 < portSelect < 65536:
 +                        print("Port sélectionné{}".format(portSelect))
 +                        portACN = portSelect
 +                        break
 +                except ValueError:
 +                    print("Oops!  Réponse incorrecte, ce n'est pas un nombre compris dans la plage demandée.")
 +        except ValueError:
 +            print("Oops!  Réponse incorrecte... Réessayer...")
 +
 +    print("Installation client sur port {}.".format(portACN))
  
 def ipRecuperation(): def ipRecuperation():
-    """ Fonction récupérant l'adresse IPv 4 de la machine"""+    """ 
 +    Fonction récupérant l'adresse IPv 4 de la machine 
 +    :return: l'ip de la machine lançant ce script 
 +    """
     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)     s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
Ligne 116: Ligne 204:
  
 def ipTest(ip): def ipTest(ip):
-    """ Fonction testant la validité d'une adresse IPv4 """+    """ 
 +    Fonction testant la validité d'une adresse IPv4 
 +    :param ip: ip à tester 
 +    :return: True si IP valide, False sinon 
 +    """
     reg = r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"     reg = r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
     if re.match(reg, ip):     if re.match(reg, ip):
Ligne 124: Ligne 216:
  
  
-# =========================== 
-# Lancement du script 
-# ========================== 
 def clientServeur(): def clientServeur():
-    """ Fonction déterminant s'il s'agit d'une installation de type Serveur ou Client +    """ 
-        Retourne une variable string +    Fonction déterminant s'il s'agit d'une installation de type Serveur ou Client 
-        """+    :return: Retourne une variable string soit client soit serveur 
 +    """
     while True:     while True:
         try:         try:
Ligne 144: Ligne 234:
     return choixInstall     return choixInstall
  
 +def portStatus(ip, port):
 +    """
 +    Fonction de scanne d'un port d'une machine en fonction de son IP
 +    :param ip: IP de la machine à scanner
 +    :param port: port à scanner
 +    :return: Retourne True si port ouvert ou False si port fermé
 +    """
  
-Procédure d'installation +    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
-choixInstall clientServeur() +    sock.settimeout(1)  # 
-if choixInstall.lower() == 'serveur': +    result = sock.connect_ex((ip, port)) 
-    installServeur() +    if result == 0: 
-else+        message = str(ip) + ' : Le port ' + str(port) + ' est ouvert. Possibilié de serveur ACN.' 
-    # Installation client +        print(message) 
-    while True: +        return True 
-        try: +    else: 
-            ipServeur = input("Saisir l'IP du Serveur :") +        message = str(ip) + ' : Le port est fermé. Code d\'erreur de retour; ' + str(result) 
-            if ipTest(ipServeur) is True: +        message += '. Pas de serveur ACN' 
-                break +        print(message) 
-        except ValueError: +        return False 
-            print("Oops!  Réponse incorrecte... Réessayer..."+ 
-    installClient(ipServeur)+def chercherServeurACN(ip,port): 
 +    """ 
 +    Fonction recherchant 
 +    :param ip: IP du client lançant le scan, permet de trouver un motif réseau 
 +    :param port: port à scanner (port ACN) 
 +    :return: retourne une liste contenant les IP possibles des machines ayant port spécifié ouvert 
 +    """ 
 +    ipModele = '' 
 +    listeHosts = [] 
 +    ipServeurACN = [] 
 + 
 + 
 +    # Création d'un motif pour le scan reseau 
 +    ipSplit = ip.split('.'
 +    for i in range (0,3): 
 +        ipModele += ipSplit[i] + '.' 
 +    ipModele += '0' 
 + 
 +    # debug 
 +    print('=' * 40) 
 +    print('Votre machine possède l\'ip {}.\r\nLe motif de scan sera donc : {}'. format(ip,ipModele)) 
 + 
 +    # Scan reseau à la recherche de clients 
 +    nm = nmap.PortScanner() # instantiate nmap.PortScanner object 
 +    nm.scan(hosts=ipModele+'/24', arguments='-n -sP'
 +    for host in nm.all_hosts(): 
 +        print('----------------------------------------------------'
 +        print('Host : %s (%s)' % (host, nm[host].hostname())) 
 +        print('State : %s' % nm[host].state()) 
 +        # Creation d'un mappage reseau 
 +        listeHosts.append(host) 
 + 
 +    # Sca, port ACN des clients 
 +    print('=' * 40) 
 +    print('Résultats du scan réseau : (True si port Apt-cache-server trouvé.'
 +    # Pour chacune des machines du réseau, on teste le port d'ACN (par defaut 3142 
 +    for i in listeHosts: 
 +        testPort = portStatus(i, port) 
 +        # Si réponse True, c'est le serveur 
 +        if testPort == True: 
 +            ipServeurACN.append(i) 
 +            message = 'Eventuel Serveur ACN.' 
 +        else: 
 +            message = 'Pas de port ACN ouvert' 
 +        print(i, ' : ', testPort, '. ', message) 
 + 
 +    return ipServeurACN 
 + 
 +def validerIpServeurACN(listIp): 
 +    """ 
 +    Fonction recupérant la liste des machines susceptibles d'être serveur ACN 
 +    Teste de cette liste pour valider ces IP ou les infirmer 
 +    :param listIp: liste contenant les IP des machines écoutant le port ACN 
 +    :return: IP de la machine sélectionnée comme serveur ACN 
 +    """ 
 +    if len(listIp) == 0: 
 +        sys.exit('Aucun serveur ACN de trouver. Merci de vérifier son installation.\r\n' 
 +                 'Relancer ce script sur la machine serveur.\r\n' 
 +                 'Et sélectionner "Installation Serveur"\r\n'
 +    elif len(listIp) == 1: 
 +        print('Serveur ACN possible : ',listIp[0]
 +        while True: 
 +            try: 
 +                ouiNon = input("Valider ce choix ? (Oui / Non) ") 
 +                if ouiNon.lower() == 'oui': 
 +                    print('IP du serveur : ', listIp[0] ) 
 +                    ipServeur = listIp[0] 
 +                    break 
 +                elif ouiNon.lower() == 'non': 
 +                    sys.exit('Revoir la configuration du serveur.\n' 
 +                             'Et relancer ce script.\n' 
 +                             'Aucune machine disponible dans le reseau actuellement ' 
 +                             'avec ce port d\'ouvert'
 +            except ValueError: 
 +                print("Oops!  Réponse incorrecte... Réessayer... [Oui / Non ]") 
 +        # Valider l'ip unique 
 +    else: 
 +        print('Plusieurs machines pouvant être des serveurs ACN'
 +        print('Veuillez sélectionner une ip, merci :') 
 +        for i in enumerate(listIp): 
 +            print('Choix ', i[0] + 1, ' : ', i[1]) 
 +        # Installation client 
 +        while True: 
 +            try: 
 +                ipServeur = input("Saisir l'IP du Serveur :") 
 +                if ipTest(ipServeur) is True and ipServeur in listIp
 +                    break 
 +            except ValueError: 
 +                print("Oops!  Réponse incorrecte... Réessayer..."
 +    return ipServeur 
 + 
 + 
 +def installCronApt(distrib): 
 +    """ 
 +    Fonction Recuperation des entrées des mises à jour de sécurité dans 
 +     dans les divers sources.list possibles 
 +     Et création d'un sources.list basé que sur ces entrées (security) 
 +     Le fichier est propre à primtux. Donc si existe, on le régénère sinon on le crée 
 +     Et envoi mail sur root 
 +    :param distrib: Ubuntu ou Debian 
 +    :return: None 
 +    """ 
 + 
 +    mailRoot = 'root' 
 +    aptSecurity = "find /etc/apt -type f -name '*.list' " \ 
 +                  "| xargs cat " \ 
 +                  " grep -v \"^#\" | grep security" 
 + 
 +    # Installation de cron-apt 
 +    installPackage('cron-apt',distrib) 
 + 
 +    # Création sources.list spécial sécurité 
 +    log = open('/etc/apt/sources.list.d/security-primtuxACN.list', 'w'
 +    log.write('# Security Update. For Primtux Apt-cacher-ng.\n'
 +    log.flush() 
 +    c = subprocess.call(aptSecurity, stdout=log, stderr=log, shell=True) 
 + 
 +    # Configuration d'une action dans la conf de cron-apt 
 +    # /etc/cron-apt/action.d/5-primtuxACN-security 
 +    fichier = open('/etc/cron-apt/action.d/5-primtuxACN-security', "w"
 +    fichier.write("upgrade -y -o APT::Get::Show-Upgraded=true\n"
 +    fichier.write("OPTIONS=\"-o quiet=1 -o APT::Get::List-Cleanup=false -o " 
 +                  "Dir::Etc::SourceList=/etc/apt/sources.list.d/security-primtuxACN.list " 
 +                  "-o Dir::Etc::SourceParts=\\\"/dev/null\\\"\"\n"
 +    fichier.write("MAILTO=\"{}\"\n".format(mailRoot)) 
 +    fichier.write("MAILON=\"always\"\n"
 +    fichier.close() 
 + 
 +    print("Dès lors, le système installera les mises à jour de sécurité, toutes les nuits  à 4 heures."
 + 
 +    return None 
 + 
 + 
 + 
 +def main(): 
 +    """ 
 +    Lancement du script 
 +    :return: None 
 +    """ 
 +    # Défnition du port par defaut d'ACN 
 +    portACN = 3142 
 +    # Recupere le type de distribution faisant tourner le script 
 +    distrib  = baseDebian() 
 + 
 +    choixInstall = clientServeur() 
 +    if choixInstall.lower() == 'serveur': 
 +        ipServeur = ipRecuperation() 
 +        installServeur(ipServeur, portACN, distrib) 
 +    else: 
 +        # Installation client 
 +        portSelection(portACN) 
 +        ip = ipRecuperation() 
 +        ipServeur = chercherServeurACN(ip, portACN) 
 +        ipServeur = validerIpServeurACN(ipServeur) 
 +        installClient(ipServeur,portACN) 
 + 
 +    # Que ce sont pour l'un ou l'autre, install cron-apt auto securité 
 +    installCronApt(distrib) 
 +    return None 
 + 
 +""" 
 + Boucle main() 
 +""" 
 +if __name__ == "__main__": 
 +    # execute only if run as a script 
 +    main()
 </code> </code>
 +
  
 ===== Liens ===== ===== Liens =====
python/acn-py-installer.txt · Dernière modification : 2020/02/12 21:08 de crust