wireguardCreate.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import smtplib
  5. import subprocess
  6. import textwrap
  7. import tempfile
  8. from email.mime.multipart import MIMEMultipart
  9. from email.mime.text import MIMEText
  10. def check_env (member_id):
  11. """
  12. Checks if wireguard is correctly installed, the script is run as
  13. root and the member id is correct.
  14. """
  15. wgInstalled = os.system("wg")
  16. if os.geteuid() != 0:
  17. print("On a besoin des droits root pour créer un accès VPN.")
  18. print("Relancez la commande préfixée d'un sudo.")
  19. raise Exception("Got root?")
  20. if wgInstalled != 0:
  21. print("Wireguard ne semble pas être installé sur votre système.")
  22. print("Il faudrait installer wireguard-tools et wireguard-dkms avant\
  23. d'utiliser ce script")
  24. raise Exception("Install wg")
  25. if member_id < 2 or member_id > 253:
  26. print("On est parti du principe que les IDs des membres commencent à 1.")
  27. print("Ah, aussi, pour le moment, on est aussi partis du principe que ça \
  28. s'arrête à 253.")
  29. print("Si on a plus de 253 membres, premièrement, FÉLICITATIONS venant\
  30. du Félix du passé. Par contre, il faut repenser l'adressage des \
  31. IPs du VPN maintenant :( Ranson du succès j'immagine.")
  32. raise Exception("Wrong member_id")
  33. def gen_wg_keys (temp_dir):
  34. """
  35. Generates both the private and the public wireguard key of the new member.
  36. """
  37. pubkey_path = os.path.join(temp_dir, "pub.key")
  38. privkey_path = os.path.join(temp_dir, "priv.key")
  39. psk_path = os.path.join(temp_dir, "psk.key")
  40. subprocess.run(\
  41. "wg genkey | tee %s | wg pubkey > %s" % (privkey_path, pubkey_path),\
  42. shell=True, check=True)
  43. subprocess.run("wg genpsk > %s" % (psk_path), shell=True, check=True)
  44. return (privkey_path, pubkey_path, psk_path)
  45. def update_wg_config (member_id, config_file, pubkey_path, psk_path):
  46. """
  47. Generate the wireguard configuration for this new member.
  48. """
  49. wg_new_peer = '''
  50. [Peer]
  51. PublicKey = %PUBKEY%
  52. PresharedKey = %PSK%
  53. AllowedIPs = 10.0.0.{1}/24, fd00::{1}/64
  54. '''.format(member_id)
  55. with open(config_file, "a") as wg_file:
  56. wg_file.write(wg_config)
  57. subprocess.run('sed -i "s/%PUBKEY%/$(cat %s)/" "%s"' % (pubkey_path, config_file), shell=True, check=True)
  58. subprocess.run('sed -i "s/%PSK%/$(cat %s)/" "%s"' % (psk_path, config_file), shell=True, check=True)
  59. class Email:
  60. """
  61. Not really necessary, but I keep on forgetting most of an email arguments
  62. and I'm tired of debugging this class of error... Too bad we don't have any
  63. record type in this language.
  64. PS: I hate python.
  65. """
  66. def __init__(self, username, passwd, from_addr, to_addr, server):
  67. self.username = username
  68. self.passwd = passwd
  69. self.from_addr = from_addr
  70. self.to_addr = to_addr
  71. self.server = server
  72. def send_mail(email, wgconfig_path):
  73. """
  74. Send the private key by email.
  75. email:
  76. - username
  77. - passwd
  78. - from_addr
  79. - to_addr
  80. - server
  81. """
  82. from_addr = 'bureau@baionet.fr'
  83. password = email.passwd
  84. msg = MIMEMultipart()
  85. msg['Subject'] = "Votre acces VPN Baionet"
  86. msg['Date'] = formatdate(localtime=True)
  87. msg['From'] = email.from_addr
  88. msg['To'] = [email.to_addr]
  89. body = textwrap.dedent('''
  90. blahblah, cf le wiki blahblahblah
  91. ''')
  92. msg.attach([MIMEText(body), MIMEText(config)])
  93. with open(wgconfig_path, "rb") as f:
  94. part = MIMEApplication(
  95. f.read(),
  96. Name=os.path.basename(f))
  97. part['Content-Disposition'] = 'attachment; filename=%s' % basename(f)
  98. msg.attach(part)
  99. username = email.username
  100. server = smtplib.SMTP(email.server)
  101. server.ehlo()
  102. server.starttls()
  103. server.login(email.username, email.passwd)
  104. server.sendmail(email.from_addr, email.to_addr, msg.as_string())
  105. server.quit()
  106. # Main Function
  107. # =============
  108. # *************
  109. # =============
  110. # 1- Parse email/member id.
  111. # 2- Génère les clés wireguard.
  112. # 3- Crée/déploie la configuration wireguard.
  113. # 5- Envoie la clé à l'utilisateur (email/manuellement)
  114. if __name__ == '__main__':
  115. member_email = input("EMail du nouveau membre: ")
  116. try:
  117. member_id = int(input("Numéro d'adhérant du nouveau membre: "))
  118. except Exception as e:
  119. print("ERREUR: Le numéro d'adhérant est en théorie un entier entre 1 et 253.")
  120. sys.exit(1)
  121. try:
  122. service_name = os.environ['SYSTEMD_SERVICE']
  123. wg_config_dir = os.environ['WG_CONF_PATH']
  124. check_env(member_id)
  125. except Exception as e:
  126. print("ERREUR: problème d'environnement: {}".format(e))
  127. sys.exit(1)
  128. print("[+] Génération des clés wireguard")
  129. with tempfile.TemporaryDirectory() as temp_dir:
  130. (privkey_path, pubkey_path, psk_path) = gen_wg_keys(temp_dir)
  131. print("[+] Modification de la configuration wireguard")
  132. try:
  133. update_wg_config(member_id, config_file, pubkey_path, psk_path)
  134. except Exception as e:
  135. print("ERREUR: Problème lors de la génération des clés wireguard.")
  136. print(e)
  137. sys.exit(1)
  138. print("[+] Chargement de la nouvelle interface réseau")
  139. try:
  140. os.system("systemctl restart %s" % (service_name))
  141. except Exception as e:
  142. print("ERREUR: Problème lors du redémarrage du service.")
  143. print("[+] Envoi de la clé privée au nouveau membre")
  144. try:
  145. username = os.environ['SMTP_USERNAME']
  146. passwd = os.environ['SMTP_PASSWD']
  147. server = os.environ['SMTP_SERVER']
  148. server = os.environ['SYSTEMD_SERVICE']
  149. server = os.environ['SYSTEMD_SERVICE']
  150. email = Email(username, passwd, "bureau@baionet.fr", member_email, server)
  151. send_email(email, privkey_path)
  152. except Exception as e:
  153. print("ERREUR: erreur lors de l'envoi de l'email.")
  154. print("Veuillez envoyer tout ce message d'erreur à la liste de diffusion technique")
  155. print(e)
  156. sys.exit(1)
  157. print("[+] Nettoyage")
  158. print("[+] DONE")