gtk3-listdomains.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import gi
  2. gi.require_version('Gtk', '3.0')
  3. from gi.repository import GLib, Gtk, GObject
  4. import json
  5. from nginxparser import loads
  6. import os
  7. import re
  8. import spur
  9. import threading
  10. import time
  11. DIR_PATH = os.path.dirname(os.path.realpath(__file__))
  12. VHOSTS_PATH = DIR_PATH + '/nginx-vhosts'
  13. if not os.path.isdir(VHOSTS_PATH):
  14. os.mkdir(VHOSTS_PATH)
  15. fp = open('creds.json', 'r')
  16. creds = json.load(fp)
  17. def ssh_command(command, sudo=False):
  18. shell = spur.SshShell(
  19. hostname=creds['host'],
  20. username=creds['user'],
  21. password=creds['passphrase'],
  22. private_key_file=creds['ssh_key_path'])
  23. with shell:
  24. command_bits = command.split(" ")
  25. if sudo:
  26. command_bits.insert(0, "sudo")
  27. process = shell.spawn(command_bits)
  28. if sudo:
  29. process.stdin_write(creds['password'])
  30. result = process.wait_for_result()
  31. return result.output.decode()
  32. #
  33. # def get_check_domain_command(domain):
  34. # return "sudo openssl x509 -text -in /etc/letsencrypt/live/" + domain + "/fullchain.pem"
  35. #
  36. # def join_commands(commands):
  37. # return " && ".join(commands)
  38. class EntryWindow(Gtk.Window):
  39. def __init__(self):
  40. Gtk.Window.__init__(self, title="Entry Demo")
  41. self.set_size_request(200, 100)
  42. self.timeout_id = None
  43. vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
  44. self.add(vbox)
  45. self.progressbar = Gtk.ProgressBar(show_text=True)
  46. # self.progressbar.set_fraction(0.0)
  47. vbox.pack_start(self.progressbar, True, True, 0)
  48. hbox = Gtk.Box(spacing=6)
  49. vbox.add(hbox)
  50. self.entry_passphrase = Gtk.Entry()
  51. # https://developer.gnome.org/gtk3/stable/GtkEntry.html#gtk-entry-set-invisible-char
  52. self.entry_passphrase.set_visibility(False)
  53. # self.entry_passphrase.set_text("Enter SSH key passphrase")
  54. hbox.pack_start(self.entry_passphrase, True, True, 0)
  55. self.entry_password = Gtk.Entry()
  56. self.entry_password.set_visibility(False)
  57. # self.entry_password.set_text("Enter sudo user password")
  58. hbox.pack_start(self.entry_password, True, True, 0)
  59. self.button = Gtk.Button(label="Click Here")
  60. self.button.connect("clicked", self.on_button_clicked)
  61. hbox.pack_start(self.button, True, True, 0)
  62. #Setting up the self.grid in which the elements are to be positionned
  63. self.grid = Gtk.Grid()
  64. self.grid.set_column_homogeneous(True)
  65. self.grid.set_row_homogeneous(True)
  66. vbox.add(self.grid)
  67. #Creating the TreeStore model
  68. self.vhost_treestore = Gtk.ListStore(int, str, str)
  69. vhost_list = [
  70. # (80, "00-benoithubert.net", "benoithubert.net"),
  71. # (80, "jsx.fr", "jsx.fr")
  72. ]
  73. for vhost in vhost_list:
  74. self.vhost_treestore.append(list(vhost))
  75. self.language_filter = self.vhost_treestore.filter_new()
  76. self.language_filter.set_visible_func(self.filter_func)
  77. #creating the treeview, making it use the filter as a model, and adding the columns
  78. self.treeview = Gtk.TreeView.new_with_model(self.language_filter)
  79. for i, column_title in enumerate(["Port", "File path", "Root domain"]):
  80. renderer = Gtk.CellRendererText()
  81. column = Gtk.TreeViewColumn(column_title, renderer, text=i)
  82. self.treeview.append_column(column)
  83. self.scrollable_treelist = Gtk.ScrolledWindow()
  84. self.scrollable_treelist.set_vexpand(True)
  85. self.grid.attach(self.scrollable_treelist, 0, 0, 8, 10)
  86. self.scrollable_treelist.add(self.treeview)
  87. def filter_func(self, model, iter, data):
  88. return True
  89. def update_progess(self, domain):
  90. self.progressbar.pulse()
  91. self.progressbar.set_text('Done: ' + domain)
  92. return False
  93. def get_https_domains(self):
  94. for d in self.domains:
  95. GLib.idle_add(self.get_https_subdomains_for_domain, d)
  96. time.sleep(0.4)
  97. def get_nginx_vhosts(self):
  98. for v in self.vhosts:
  99. GLib.idle_add(self.get_nginx_vhost, v)
  100. time.sleep(0.4)
  101. def start_thread(self, func):
  102. thread = threading.Thread(target=func)
  103. thread.daemon = True
  104. thread.start()
  105. def on_button_clicked(self, widget):
  106. decoded = ssh_command("ls /etc/nginx/sites-enabled")
  107. vhosts = decoded.split("\n")
  108. vhosts.pop()
  109. self.vhosts = vhosts
  110. self.num_vhosts = len(vhosts)
  111. self.vhosts_done = 0
  112. decoded = ssh_command("ls /etc/letsencrypt/live", True)
  113. domains = decoded.split("\n")
  114. domains.pop()
  115. self.domains = domains
  116. self.num_domains = len(domains)
  117. self.domains_done = 0
  118. self.start_thread(self.get_nginx_vhosts)
  119. # self.start_thread(self.get_https_domains)
  120. # subdomains = [self.get_https_subdomains_for_domain(d) for d in domains]
  121. # subdomains_dict = dict(zip(domains, subdomains))
  122. # print(subdomains_dict)
  123. def get_nginx_vhost(self, vhost):
  124. print(vhost)
  125. vhost_file = VHOSTS_PATH + '/' + vhost
  126. if not os.path.isfile(vhost_file):
  127. print("not found locally: " + vhost_file)
  128. vhost_content = ssh_command("cat /etc/nginx/sites-enabled/" + vhost)
  129. vhost_fp = open(vhost_file, "w")
  130. vhost_fp.write(vhost_content)
  131. vhost_fp.close()
  132. else:
  133. print("found locally: " + vhost_file)
  134. vhost_fp = open(vhost_file, "r")
  135. vhost_content = vhost_fp.read()
  136. vhost_fp.close()
  137. parsed = loads(vhost_content)
  138. port_subdmomains = {}
  139. for server in parsed:
  140. server_inner = server[1]
  141. port = 0
  142. subdomains = []
  143. for directive in server_inner:
  144. if not port and "listen" in directive:
  145. p = re.compile('(\d+)')
  146. # print('listen')
  147. ports = p.findall(directive[1])
  148. port = int(ports[0])
  149. if "server_name" in directive:
  150. # print('server_name')
  151. # print(directive)
  152. subd_trimmed = directive[1].strip()
  153. subdomains = subd_trimmed.split(' ')
  154. port_subdmomains[port] = subdomains
  155. for subd in subdomains:
  156. self.vhost_treestore.append([port, vhost, subd])
  157. # print(port_subdmomains)
  158. self.vhosts_done += 1
  159. percent_done = self.vhosts_done * 1.0 / self.num_vhosts
  160. self.progressbar.set_fraction(percent_done)
  161. return False
  162. def get_https_subdomains_for_domain(self, domain):
  163. # print(domain)
  164. p = re.compile('DNS:([0-9a-z-.]+)')
  165. cert_data = ssh_command("sudo openssl x509 -text -in /etc/letsencrypt/live/" + domain + "/fullchain.pem", True)
  166. self.domains_done += 1
  167. percent_done = self.domains_done * 1.0 / self.num_domains
  168. # print(percent_done)
  169. self.progressbar.set_fraction(percent_done)
  170. # self.progressbar.set_text('Done: ' + domain)
  171. # print(cert_data)
  172. # return p.findall (cert_data)
  173. return False
  174. def app_main():
  175. win = EntryWindow()
  176. win.connect("delete-event", Gtk.main_quit)
  177. win.show_all()
  178. if __name__ == '__main__':
  179. import signal
  180. signal.signal(signal.SIGINT, signal.SIG_DFL)
  181. # Calling GObject.threads_init() is not needed for PyGObject 3.10.2+
  182. GObject.threads_init()
  183. app_main()
  184. Gtk.main()