-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlauncher.py
More file actions
252 lines (212 loc) · 8.27 KB
/
launcher.py
File metadata and controls
252 lines (212 loc) · 8.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/usr/bin/env python3
#
# Graphical secure Launcher to connect to remote drives via SSH
# Provides a simple GUI to input credentials and select drives
# Executes a bash script with the provided parameters securely
#
# Author: Anton Chernov
# Date: Feb 3, 2026
# License: MIT
#
# Version 1.0.0 - initial release
# Version 1.1.0 - added block/unblock fields based on drive selection,
# improved log parsing to show only relevant error messages,
# improved passing sensitive data to subprocess (replaced
# environment variables with stdin), added Usage and About
# dialogs.
# Version 1.2.0 - replaced hardcoded script path with environment variable,
# added minor changes to UI layout.
#
import os
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import subprocess
import re
VERSION = "1.2.0"
SELECT_STR = "Selected: "
DEFAULT_DRIVE = "Drive G"
#------------------------------------------------------------------------------
def main() -> None:
PADX = 10 # Padding for x-axis
PADY = 2 # Padding for y-axis
# Path to log directory
LOG_PATH='/var/log'
# Path to bash script (set via environment variable)
SCRIPT_PATH = (os.environ.get("ADMIN_SCRIPTS") or ".") + "/Connect2Server"
#------------------------------------------------------------------------------
def select(event):
selected_item = combo_box.get()
drive_entry.config(text=SELECT_STR + selected_item)
if selected_item == "Unmount":
# Block fields
user_entry.config(state="disabled")
password_entry.config(state="disabled")
else:
# Allow fields
user_entry.config(state="normal")
password_entry.config(state="normal")
#------------------------------------------------------------------------------
def truncate_log(log: str) -> str:
res_str = ""
lines = log.split('\n')
for line in lines:
if re.search(r' - ', line):
res_str += line.split(' - ', 1)[1] + '\n'
# Return truncated string without trailing newline
return res_str.rstrip('\n')
#------------------------------------------------------------------------------
def run_script() -> None:
sudo_pass = sudo_entry.get()
user = user_entry.get()
password = password_entry.get()
selected = combo_box.get()
if selected == "Unmount":
if not sudo_pass:
messagebox.showwarning(
"Warning", "Please fill security password."
)
return
# Launch bash-script without drive parameter
cmd = [
"sudo", "-E", "-S", "{}/connect".format(SCRIPT_PATH),
"-l", LOG_PATH
]
input_data = f"{sudo_pass}\n".encode()
else:
if not sudo_pass or not user or not password:
messagebox.showwarning("Warning", "Please fill in all fields.")
return
drive = selected.split()[-1].lower()
# Launch bash-script with drive parameter
cmd = [
"sudo", "-E", "-S", "{}/connect".format(SCRIPT_PATH),
"-d", drive, "-l", LOG_PATH
]
input_data = f"{sudo_pass}\n{user}\n{password}\n".encode()
try:
proc = subprocess.Popen(
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout, stderr = proc.communicate(input=input_data)
if proc.returncode == 0:
messagebox.showinfo("Success", "Script executed successfully!")
else:
err_str = stderr.decode().strip()
if re.search(r'incorrect password attempt', err_str):
err_str = "Incorrect security password."
else:
err_str = truncate_log(err_str)
messagebox.showerror(
"Error", "Failed to execute script.\n{}".format(err_str)
)
except Exception as e:
messagebox.showerror(
"Error", "Error executing script: {}".format(str(e))
)
finally:
# Clear sensitive data from memory
sudo_pass = None
user = None
password = None
root.quit()
#------------------------------------------------------------------------------
def show_usage() -> None:
usage_window = tk.Toplevel(root)
usage_window.title("Usage")
usage_window.geometry("430x215")
text = tk.Text(usage_window, wrap=tk.WORD, padx=10, pady=10)
text.pack(fill=tk.BOTH, expand=True)
usage_text = """
1. Enter your security password in the first field
2. Enter the server username in the second field
3. Enter the user password in the third field
4. Select the drive from the dropdown menu
5. Click "Run" to execute the connection
The application will connect to the specified drive
using the provided credentials and then close.
"""
text.insert(tk.END, usage_text)
text.config(state=tk.DISABLED)
#------------------------------------------------------------------------------
def show_about() -> None:
about_window = tk.Toplevel(root)
about_window.title("About")
about_window.geometry("430x385")
text = tk.Text(about_window, wrap=tk.WORD, padx=10, pady=10)
text.pack(fill=tk.BOTH, expand=True)
about_text = """
Secure Launcher v{}
This application provides a graphical interface
for securely connecting to remote network drives.
Main features:
- Simple GUI built with Python and Tkinter
- Secure handling of user and password input
- Integration with system bash scripts
- Support for mounting and unmounting drives
- Logging of operations for troubleshooting
Usage:
Enter your credentials, select the desired drive,
and the launcher will execute the connection script
with elevated privileges in a safe way.
© 2026 Anton Chernov. Licensed under MIT.
""".format(VERSION)
text.insert(tk.END, about_text)
text.config(state=tk.DISABLED)
#------------------------------------------------------------------------------
root = tk.Tk() # Object of the main application window
root.title("Connect to Server") # Set window title
root.geometry("250x270") # Set window size (width x height)
# Create a menu bar
menu = tk.Menu(root)
root.config(menu=menu)
filemenu = tk.Menu(menu)
menu.add_cascade(label='File', menu=filemenu)
filemenu.add_command(label='Exit', command=root.quit)
helpmenu = tk.Menu(menu)
menu.add_cascade(label='Help', menu=helpmenu)
helpmenu.add_command(label='Usage', command=show_usage)
helpmenu.add_separator()
helpmenu.add_command(label='About', command=show_about)
# Create an entry for privileged access rights
tk.Label(root, text="Security password:").pack()
sudo_entry = tk.Entry(root, show="*")
sudo_entry.pack(pady=PADY, padx=PADX)
# Create an entry for server user name
tk.Label(root, text="Server user:").pack()
user_entry = tk.Entry(root)
user_entry.pack(pady=PADY, padx=PADX)
# Create an entry for server user password
tk.Label(root, text="User password:").pack()
password_entry = tk.Entry(root, show="*")
password_entry.pack(pady=PADY, padx=PADX)
# Create a label
drive_entry = tk.Label(root, text=SELECT_STR + DEFAULT_DRIVE)
drive_entry.pack(pady=PADY, padx=PADX)
# Create a Combobox widget
combo_box = ttk.Combobox(
root, values=[
"Drive D",
"Drive E",
"Drive G",
"Drive H",
"Drive I",
"Unmount"
],
justify='center'
)
# Set the size of the Combobox
combo_box.pack(pady=15, padx=20)
# Set default value
combo_box.set(DEFAULT_DRIVE)
# Bind event to selection
combo_box.bind("<<ComboboxSelected>>", select)
# Create a button to run the script
tk.Button(root, text="Run", command=run_script).pack()
# Start the main event loop
root.mainloop()
# This allows the script to be imported as a module
# without executing the main function
if __name__ == "__main__":
main()