123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #!/usr/bin/env python3
- import os
- import sys
- import smtplib
- import subprocess
- import textwrap
- import tempfile
- from email.mime.multipart import MIMEMultipart
- from email.mime.text import MIMEText
- def check_env (member_id):
- """
- Checks if wireguard is correctly installed, the script is run as
- root and the member id is correct.
- """
- wgInstalled = os.system("wg")
- if os.geteuid() != 0:
- print("On a besoin des droits root pour créer un accès VPN.")
- print("Relancez la commande préfixée d'un sudo.")
- raise Exception("Got root?")
- if wgInstalled != 0:
- print("Wireguard ne semble pas être installé sur votre système.")
- print("Il faudrait installer wireguard-tools et wireguard-dkms avant\
- d'utiliser ce script")
- raise Exception("Install wg")
- if member_id < 2 or member_id > 253:
- print("On est parti du principe que les IDs des membres commencent à 1.")
- print("Ah, aussi, pour le moment, on est aussi partis du principe que ça \
- s'arrête à 253.")
- print("Si on a plus de 253 membres, premièrement, FÉLICITATIONS venant\
- du Félix du passé. Par contre, il faut repenser l'adressage des \
- IPs du VPN maintenant :( Ranson du succès j'immagine.")
- raise Exception("Wrong member_id")
- def gen_wg_keys (temp_dir):
- """
- Generates both the private and the public wireguard key of the new member.
- """
- pubkey_path = os.path.join(temp_dir, "pub.key")
- privkey_path = os.path.join(temp_dir, "priv.key")
- psk_path = os.path.join(temp_dir, "psk.key")
- subprocess.run(\
- "wg genkey | tee %s | wg pubkey > %s" % (privkey_path, pubkey_path),\
- shell=True, check=True)
- subprocess.run("wg genpsk > %s" % (psk_path), shell=True, check=True)
- return (privkey_path, pubkey_path, psk_path)
- def update_wg_config (member_id, config_file, pubkey_path, psk_path):
- """
- Generate the wireguard configuration for this new member.
- """
- wg_new_peer = '''
- [Peer]
- PublicKey = %PUBKEY%
- PresharedKey = %PSK%
- AllowedIPs = 10.0.0.{1}/24, fd00::{1}/64
- '''.format(member_id)
- with open(config_file, "a") as wg_file:
- wg_file.write(wg_config)
- subprocess.run('sed -i "s/%PUBKEY%/$(cat %s)/" "%s"' % (pubkey_path, config_file), shell=True, check=True)
- subprocess.run('sed -i "s/%PSK%/$(cat %s)/" "%s"' % (psk_path, config_file), shell=True, check=True)
- class Email:
- """
- Not really necessary, but I keep on forgetting most of an email arguments
- and I'm tired of debugging this class of error... Too bad we don't have any
- record type in this language.
- PS: I hate python.
- """
- def __init__(self, username, passwd, from_addr, to_addr, server):
- self.username = username
- self.passwd = passwd
- self.from_addr = from_addr
- self.to_addr = to_addr
- self.server = server
- def send_mail(email, wgconfig_path):
- """
- Send the private key by email.
- email:
- - username
- - passwd
- - from_addr
- - to_addr
- - server
- """
- from_addr = 'bureau@baionet.fr'
- password = email.passwd
- msg = MIMEMultipart()
- msg['Subject'] = "Votre acces VPN Baionet"
- msg['Date'] = formatdate(localtime=True)
- msg['From'] = email.from_addr
- msg['To'] = [email.to_addr]
- body = textwrap.dedent('''
- blahblah, cf le wiki blahblahblah
- ''')
- msg.attach([MIMEText(body), MIMEText(config)])
- with open(wgconfig_path, "rb") as f:
- part = MIMEApplication(
- f.read(),
- Name=os.path.basename(f))
- part['Content-Disposition'] = 'attachment; filename=%s' % basename(f)
- msg.attach(part)
- username = email.username
- server = smtplib.SMTP(email.server)
- server.ehlo()
- server.starttls()
- server.login(email.username, email.passwd)
- server.sendmail(email.from_addr, email.to_addr, msg.as_string())
- server.quit()
- # Main Function
- # =============
- # *************
- # =============
- # 1- Parse email/member id.
- # 2- Génère les clés wireguard.
- # 3- Crée/déploie la configuration wireguard.
- # 5- Envoie la clé à l'utilisateur (email/manuellement)
- if __name__ == '__main__':
- member_email = input("EMail du nouveau membre: ")
- try:
- member_id = int(input("Numéro d'adhérant du nouveau membre: "))
- except Exception as e:
- print("ERREUR: Le numéro d'adhérant est en théorie un entier entre 1 et 253.")
- sys.exit(1)
- try:
- service_name = os.environ['SYSTEMD_SERVICE']
- wg_config_dir = os.environ['WG_CONF_PATH']
- check_env(member_id)
- except Exception as e:
- print("ERREUR: problème d'environnement: {}".format(e))
- sys.exit(1)
- print("[+] Génération des clés wireguard")
- with tempfile.TemporaryDirectory() as temp_dir:
- (privkey_path, pubkey_path, psk_path) = gen_wg_keys(temp_dir)
- print("[+] Modification de la configuration wireguard")
- try:
- update_wg_config(member_id, config_file, pubkey_path, psk_path)
- except Exception as e:
- print("ERREUR: Problème lors de la génération des clés wireguard.")
- print(e)
- sys.exit(1)
- print("[+] Chargement de la nouvelle interface réseau")
- try:
- os.system("systemctl restart %s" % (service_name))
- except Exception as e:
- print("ERREUR: Problème lors du redémarrage du service.")
- print("[+] Envoi de la clé privée au nouveau membre")
- try:
- username = os.environ['SMTP_USERNAME']
- passwd = os.environ['SMTP_PASSWD']
- server = os.environ['SMTP_SERVER']
- server = os.environ['SYSTEMD_SERVICE']
- server = os.environ['SYSTEMD_SERVICE']
- email = Email(username, passwd, "bureau@baionet.fr", member_email, server)
- send_email(email, privkey_path)
- except Exception as e:
- print("ERREUR: erreur lors de l'envoi de l'email.")
- print("Veuillez envoyer tout ce message d'erreur à la liste de diffusion technique")
- print(e)
- sys.exit(1)
- print("[+] Nettoyage")
- print("[+] DONE")
|