forked from itachi1621/ssh-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathssh-manager.sh
More file actions
executable file
·539 lines (413 loc) · 16.6 KB
/
ssh-manager.sh
File metadata and controls
executable file
·539 lines (413 loc) · 16.6 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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
#!/bin/bash
#This script allows the user to save ssh logins and then connect to the server
#by just entering the number of the server
#I created this script because remembering all the ssh logins is a pain in the @$$
#Also i didn't want to use a programming language like python or ruby,
#because I wanted to keep it simple and avoid installing any dependencies
#I also wanted to learn more about bash scripting with awk and sed
# -- Scott Gopaulchan 2023
warning="\033[1;31m" #Red
success="\033[1;32m" #Green
info="\033[1;33m" #Yellow
reset="\033[0m" #Reset color
cfg_file_name="$HOME/.ssh_manager_config" #The file where the server details are stored
#Check if the config file exists if not create it
if [ ! -f "$cfg_file_name" ]
then
touch "$cfg_file_name"
fi
fileEmptyCheck(){
if [ ! -s "$cfg_file_name" ] # -s checks if the file is empty
then
printf "%s${warning}No SSH connections added yet${reset}\n"
menu
fi
}
addNewServerName(){
read -p "Enter the server name/alias: " name
#Check if the server name is blank
if [ -z "$name" ] # -z checks if the string is empty
then
printf "%s${warning}Server name cannot be blank${reset}\n"
addNewServerName
fi
}
editServerName(){
printf "Current name is: %s \n " "$name"
read -p "Enter the new name or leave blank to use current name : " newName
printf "\n"
if [ -z "$newName" ]
then
name=$name
else
name=$newName
fi
}
addNewServerIp(){
read -p "Enter the server IP or domain name: " ip
#Check if ip is blank and conforms to the regex pattern for ip address or domain name i.e xxx.xxx.xxx.xxx or example.com
if [ -z "$ip" ] || ! [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] && ! [[ "$ip" =~ ^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,}$ ]]
#Yeah no idea what this regex does looks like gibberish to me, I used it from stackoverflow and confimed it works using regex101.com
then
printf "%s${warning}Invalid IP or domain name${reset}\n"
addNewServerIp
fi
}
editServerIp(){
printf "Current IP is: %s \n" "$ip"
read -p "Enter the new IP or domain name or leave blank to use current IP : " newIp
printf "\n"
if [ -z "$newIp" ]
then
ip=$ip
else
if ! [[ "$newIp" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] && ! [[ "$newIp" =~ ^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,}$ ]]
then
printf "%s${warning}Invalid IP or domain name${reset}\n"
editServerIp $ip
else
ip=$newIp
fi
fi
}
addNewServerPort(){
read -p "Enter the port number leave blank for default of 22 : " port
#check if the port is blank
if [ -z "$port" ]
then
port=22
fi
#Check if the port is a number and is between 1 and 65535 (Valid Port ranges)
if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -gt 65535 ] || [ "$port" -lt 1 ]
then
printf "%s${warning}Invalid port number${reset}\n"
addNewServerPort
fi
}
editServerPort(){
printf "Current port is: %s \n " "$port"
read -p "Enter the new port number or leave blank to use current port : " newPort
printf "\n"
if [ -z "$newPort" ]
then
port=$port
else
if ! [[ "$newPort" =~ ^[0-9]+$ ]] || [ "$newPort" -gt 65535 ] || [ "$newPort" -lt 1 ]
then
printf "%s${warning}Invalid port number${reset}\n"
editServerPort $port
else
port=$newPort
fi
fi
}
addNewServerUser(){
read -p "Enter the username: " user
#Check if the user is blank
if [ -z "$user" ] # -z checks if the string is empty
then
printf "%s${warning}Username cannot be blank${reset}\n"
addNewServerUser
fi
}
editServerUser(){
printf "Current user is %s \n " "$user"
read -p "Enter the new username or leave blank to use current name : " newUser
if [ -z "$newUser" ]
then
user=$user
else
user=$newUser
fi
}
addNewServerPassword(){
read -p "Enter the password: " password
#Check if the user is blank
if [ -z "$password" ] # -z checks if the string is empty
then
printf "%s${warning}Password cannot be blank${reset}\n"
addNewServerPassword
fi
}
editServerPassword(){
printf "Current password is %s \n " "$password"
read -p "Enter the new password or leave blank to use current password : " newPassword
if [ -z "$newPassword" ]
then
user=$password
else
user=$newPassword
fi
}
addNewServerKeyFile(){
read -p "Enter the path to the key file or leave blank if not used: " keyfile
if ! [ -z "$keyfile" ]
then
#check if the key file exists
if ! [ -f "$keyfile" ]
then
printf "%s${warning}File does not exist.${reset}\n"
addNewServerKeyFile
fi
fi
}
editServerKeyFile(){
printf "Current key file is %s \n " "$keyfile"
read -p "Enter the path to the key file or leave blank to use current key file: " newKeyFile
if [ -z "$newKeyFile" ]
then
keyfile=${keyfile//\//\\/}
else
#check if the key file exists
if ! [ -f "$newKeyFile" ]
then
printf "%s${warning}File does not exist.${reset}\n"
editServerKeyFile
else
keyfile=${newKeyFile//\//\\/}
fi
fi
}
addNewServerOption(){
read -p "Enter the options leave blank if not used: " option
}
editServerOption(){
printf "Current option is %s \n " "$option"
read -p "Enter the path to the key file or leave blank to use current option: " newOption
}
createNewSSHCredentials(){
printf "%s${info}===========================${reset}\n"
echo -e "${info}Add New SSH Connection${reset}"
printf "%s${info}===========================${reset}\n"
addNewServerName
addNewServerIp
addNewServerPort
addNewServerUser
addNewServerPassword
addNewServerKeyFile
addNewServerOption
echo "$name,$ip,$port,$user,$password,$keyfile,$option," >> "$cfg_file_name"
echo -e "${success}SSH Connection added successfully${reset}"
read -p "Do you want to connect to the added SSH connection now? (y/n) " selection
if [[ $selection =~ ^[Yy]$ ]]
then
connectToSSHServer "qc"
fi
menu
}
editSSHConnection(){
fileEmptyCheck
printf "%s${info}===========================${reset}\n"
echo -e "${info} Saved SSH Connections ${reset}"
printf "%s${info}===========================${reset}\n"
#Now to use awk to list the servers in a nice format 1 , 2 , 3 etc
printf "%s${info}# Name IP/Host \tPort Username\t Password\t Key File${reset}\n"
awk -F, '{print NR " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7}' "$cfg_file_name" | column -t # -t is used to align the columns, using awk is always awkward .... but it works
printf "%s${warning}Enter the number of the SSH connection you want to edit or enter 0 to cancel : ${reset}"
read -p "" serverNumber
#Check if the user wants to cancel
if [ "$serverNumber" -eq 0 ]
then
menu
fi
if [ -z "$serverNumber" ] || ! [[ "$serverNumber" =~ ^[0-9]+$ ]] || [ "$serverNumber" -gt "$(wc -l < "$cfg_file_name")" ] || [ "$serverNumber" -lt 1 ]
then
printf "%s${warning}Invalid selection${reset}\n"
editSSHConnection # You have to love reursive functions
fi
#Now to use awk to filter the server number and get the details name,ip,host etc
name=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $1}' "$cfg_file_name")
ip=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $2}' "$cfg_file_name")
port=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $3}' "$cfg_file_name")
user=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $4}' "$cfg_file_name")
password=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $5}' "$cfg_file_name")
keyfile=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $6}' "$cfg_file_name")
option=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $7}' "$cfg_file_name")
editServerName
editServerIp
editServerPort
editServerUser
editServerPassword
editServerKeyFile
editServerOption
#Now to replace the selected lines info with the updated info to the file
sed -i "${serverNumber}s/.*/$name,$ip,$port,$user,$password,$keyfile,$option/" "$cfg_file_name"
printf "%s${success}SSH Connection has been edited${reset}\n"
menu
}
listSSHCredentials(){
fileEmptyCheck
printf "%s${info}===========================${reset}\n"
echo -e "${info} Saved SSH Connections ${reset}"
printf "%s${info}===========================${reset}\n"
#Now to use awk to list the servers in a nice format 1 , 2 , 3 etc in a table format starting with the header but starting the numbering at from the second line
printf "%s${info}# Name IP/Host Port Username Password Key file Option${reset}\n"
# -t is used to align the columns, using awk is always awkward .... but it works
awk -F, '{print NR " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7}' "$cfg_file_name" | column -t
menu
}
SSHSearchCredential(){
fileEmptyCheck
printf "%s${info}===========================${reset}\n"
echo -e "${info} Saved SSH Connections ${reset}"
printf "%s${info}===========================${reset}\n"
connection="$(cat $cfg_file_name | fzf)"
serverName=$(echo $connection | awk -F, '{print $1}')
serverIp=$(echo $connection | awk -F, '{print $2}')
serverPort=$(echo $connection | awk -F, '{print $3}')
serverUser=$(echo $connection | awk -F, '{print $4}')
serverPassword=$(echo $connection | awk -F, '{print $5}')
serverKeyFile=$(echo $connection | awk -F, '{print $6}')
serverOption=$(echo $connection | awk -F, '{print $7}')
#echo $serverPort
#Here we go connecting to the server
printf "%s${success}Connecting to ${serverName} ...${reset}\n"
if [ ! -z $serverKeyFile ];
then
commande="ssh -i "$serverKeyFile" -p "$serverPort" "$serverUser""@""$serverIp" "$serverOption""
echo $commande
$commande
elif [ ! -z $serverPassword ];
then
commande="sshpass -p "$serverPassword" ssh -p "$serverPort" "$serverUser""@""$serverIp" "$serverOption""
echo $commande
$commande
else
commande="ssh -p "$serverPort" "$serverUser""@""$serverIp" "$serverOption""
echo $commande
$commande
fi
menu
}
connectToSSHServer(){
if [ "$1" == "qc" ] #qc is the quick connect option
then
fileEmptyCheck
serverName=$name
serverIp=$ip
serverPort=$port
serverUser=$user
serverPassword=$password
serverKeyFile=$keyfile
serverOpttion=$option
else
fileEmptyCheck
printf "%s${info}===========================${reset}\n"
echo -e "${info} Saved SSH Connections ${reset}"
printf "%s${info}===========================${reset}\n"
#Now to use awk to list the servers in a nice format 1 , 2 , 3 etc
printf "%s${info}# Name \t IP/Host \tPort Username\t Password\t Key file${reset}\n"
awk -F, '{print NR " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7}' "$cfg_file_name" | column -t # -t is used to align the columns, using awk is always awkward .... but it works
printf "%s${info}Enter the number of the SSH connection you want to connect to or enter 0 to cancel : ${reset}"
read -p "" serverNumber
if [ "$serverNumber" == 0 ]
then
menu
fi
# Now we have to check if the server number is blank
# or not a number or valid using regex (I HATE REGEX )
#and the wc command to count the number of lines in the file
if [ -z "$serverNumber" ] || ! [[ "$serverNumber" =~ ^[0-9]+$ ]] || [ "$serverNumber" -gt "$(wc -l < "$cfg_file_name")" ] || [ "$serverNumber" -lt 1 ]
then
printf "%s${warning}Invalid selection ${reset}\n"
connectToSSHServer # You have to love reursive functions
fi
#Now to use awk to filter the server number and get the details
# Alright so this part is where it get bannans and confusing
# -F, is used to specify the field separator which in this case is a comma
# -v is used to pass a variable to awk,
# NR is the current line number,
#serverNumber is the variable passed to awk
# and the last part is the action to perform on the current line
# so if the current line number is equal to the server number then print the column n which we are storing in the variable
#and the last part is the file to read from
serverName=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $1}' "$cfg_file_name")
serverIp=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $2}' "$cfg_file_name")
serverPort=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $3}' "$cfg_file_name")
serverUser=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $4}' "$cfg_file_name")
serverPassword=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $5}' "$cfg_file_name")
serverKeyFile=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $6}' "$cfg_file_name")
serverOption=$(awk -F, -v serverNumber="$serverNumber" 'NR==serverNumber {print $7}' "$cfg_file_name")
echo "Option=$serverOption"
fi
#echo $serverPort
#Here we go connecting to the server
printf "%s${success}Connecting to ${serverName} ...${reset}\n"
if [ ! -z $serverKeyFile ];
then
commande="ssh -i "$serverKeyFile" -p "$serverPort" "$serverUser""@""$serverIp" "$serverOption""
#echo $commande
$commande
elif [ ! -z $serverPassword ];
then
commande="sshpass -p "$serverPassword" ssh -p "$serverPort" "$serverUser""@""$serverIp" "$serverOption""
#echo $commande
$commande
else
commande="ssh -p "$serverPort" "$serverUser""@""$serverIp" "$serverOption""
#echo $commande
$commande
fi
menu
}
deleteSSHServer(){
fileEmptyCheck
printf "%s${info}===========================${reset}\n"
echo -e "${info} Saved SSH Connections ${reset}"
printf "%s${info}===========================${reset}\n"
#Now to use awk to list the servers in a nice format 1 , 2 , 3 etc
printf "%s${info}# Name IP/Host \tPort Username${reset}\n"
awk -F, '{print NR " " $1 " " $2 " " $3 " " $4}' "$cfg_file_name" | column -t # -t is used to align the columns, using awk is always awkward .... but it works
printf "%s${warning}Enter the number of the SSH connection you want to delete or enter 0 to cancel : ${reset}"
read -p "" serverNumber
#Check if the user wants to cancel
if [ "$serverNumber" -eq 0 ]
then
menu
fi
# Now we have to check if the server number is blank
# or not a number or valid using regex (I HATE REGEX )
#and the wc command to count the number of lines in the file
if [ -z "$serverNumber" ] || ! [[ "$serverNumber" =~ ^[0-9]+$ ]] || [ "$serverNumber" -gt "$(wc -l < "$cfg_file_name")" ] || [ "$serverNumber" -lt 1 ]
then
printf "%s${warning}Invalid selection${reset}\n"
deleteSSHServer # You have to love reursive functions
fi
#Now to delete the server from the file using sed and the info from awk then save the file
# -i is used to edit the file in place
# -e is used to specify the command to run
# '' is used to specify the line number
# serverNumber is the variable passed to sed
# d is used to delete the line
# and the last part is the pattern to match
# so in this case we are matching the line number and deleting it
#Hopefully my comments are clear enough to whoever is reading this
sed -i -e ''"$serverNumber"'d' "$cfg_file_name"
printf "%s${success}SSH Connection deleted successfully${reset}\n\n"
listSSHCredentials
}
menu(){
printf "%s${info}===========================${reset}\n"
printf "%s${success}SSH Manager${reset}\n"
printf "%s${info}===========================${reset}\n"
printf "1. List Saved SSH connections \n"
printf "2. Connect to a saved SSH connection \n"
printf "3. Search and connect to a saved SSH connection \n"
printf "4. Add new SSH connection \n"
printf "5. Edit a saved SSH connection \n"
printf "%s${warning}6. Delete a saved SSH connection ${reset}\n"
printf "7. Exit\n"
printf "Enter your choice [1-7] : "
read -p "" choice
case $choice in
1) listSSHCredentials;;
2) connectToSSHServer;;
3) SSHSearchCredential;;
4) createNewSSHCredentials;;
5) editSSHConnection;;
6) deleteSSHServer;;
7) exit;;
*) printf "%s${warning}Invalid choice${reset}\n"; menu;;
esac
}
menu