-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paththe_keymaker.sh
executable file
·262 lines (224 loc) · 6.8 KB
/
the_keymaker.sh
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
#!/bin/bash
# The Keymaker v2.6.2
# o——m
#
# Generates ssh keys per remote host, creates good configs, and optionally pushes to the host.
#
# NOTE: When using Github.com set your user to git and do not set a shortname
#
# Setup: make executable via `chmod u+x the_keymaker.sh`
# Optional: OS-dependant. These have been tested on Ubuntu.
# 1) Place in /usr/local/bin/ and rename so it is available in your path; or
# 2) Create an alias to reference this file.
# Run: `./the_keymaker.sh` and enter information based on prompts.
#
# This tool was created to help developers maintain a
# succinct and relatively safe ssh config file.
################
# Variables #
################
#Generic variables
ssh_folder="$HOME/.ssh"
ssh_config_path="$ssh_folder/config"
quiet=false
verbose=false
first_key=false
#config file variables
hostname=""
shortname=""
remoteuser=""
email=""
port=""
################
# Function #
################
#Exits the program if an error status code is returned. Otherwise prints OK
catch() {
if [[ "$@" =~ ^-?[0-9]+$ ]]; then
local STATUS="$@";
else
"$@"
local STATUS=$?;
fi
if [ $STATUS -ne 0 ]; then
echo -e "[\e[31mFAILED\e[39m]";
exit $STATUS;
else
echo -e "[\e[32mOK\e[39m]";
fi
return $STATUS;
}
################
# Setup #
################
#Grab command line arguments
while [[ $# > 0 ]]; do
key="$1"
case $key in
-q|--quiet)
quiet=true
shift # past argument
;;
-v|--verbose)
verbose=true
shift
;;
*)
# unknown option
echo "Error: Unknown flag: '$key'"
exit 1;
;;
esac
done
#Mutually exclusive flags, make sure they're all good
if [[ $verbose == true && $quiet == true ]]; then
echo "Cannot be both verbose and quiet. Please choose one option or the other.";
exit 1;
fi
# Create missing folder if necessary
if [ ! -d "$ssh_folder" ]; then
if [[ $quiet == false ]]; then
echo -n "Missing folder $ssh_folder creating..."
fi
catch mkdir -p "$ssh_folder"
fi
# Create config file if necessary
if [ -f $ssh_config_path ]; then
#Check if keymaker has made on before, if not make a backup and inform user
# What's going on.
if grep -q "^#Generated by the_keymaker o——m" "$ssh_config_path"; then
if [[ $verbose == true ]]; then
echo "Config file previously created by the keymaker. Will append key."
fi
else
backup_path="$ssh_config_path.BACKUP"
echo "========================================================"
echo " WARNING"
echo " You appear to already have a config file located at:"
echo " $ssh_config_path"
echo " Therefore the keymaker will backup your config file at:"
echo " $backup_path"
echo "========================================================="
echo -n "Creating backup... "
catch mv $ssh_config_path $backup_path
echo -n "Creating new config file..."
catch touch $ssh_config_path
first_key=true
fi
else
echo -n "Missing config file, creating..."
catch touch "$ssh_config_path"
first_key=true
fi
#If this is the first key keymaker has made we want to throw some safe defaults into the config file.
if [[ $first_key == true ]]; then
echo "First SSH Key generated by keymaker, creating safe default values."
echo "#Generated by the_keymaker o——m v2.6.1" > $ssh_config_path
echo "Host *" >> $ssh_config_path
echo " VisualHostKey yes" >> $ssh_config_path
echo " ServerAliveInterval 30" >> $ssh_config_path
echo " ServerAliveCountMax 120" >> $ssh_config_path
echo " IdentitiesOnly yes" >> $ssh_config_path
echo " ForwardAgent no" >> $ssh_config_path
echo " ForwardX11 no" >> $ssh_config_path
echo " UseRoaming no" >> $ssh_config_path
fi
################
# User Input #
################
#Get hostname to use in ssh user@hostname
while [ "$hostname" == "" ]; do
read -r -p "Enter host name you wish to generate keys for: " hostname
if [ "$hostname" == "" ]; then
echo -e "[\e[31mError\e[39m] Missing hostname!";
fi
done
#This is optional and thus does not have a while loop
read -r -p "Enter a shortname for the host. eg 'sn' Allows for ssh sn. Leave blank for none: " shortname
if [ "$shortname" == "" ]; then
shortname="$hostname"
fi
#Get remote user to use in ssh user@hostname
while [ "$remoteuser" == "" ]; do
read -r -p "Enter username for remote host: " remoteuser
if [ "$remoteuser" == "" ]; then
echo -e "[\e[31mError\e[39m] Missing remote user name!";
fi
done
#Get email to use in the ssh key
while [ "$email" == "" ]; do
read -r -p "Enter your email to be associated with this key (or anything it's just a comment): " email
if [ "$email" == "" ]; then
echo -e "[\e[31mError\e[39m] Missing email!";
fi
done
read -r -p "Port (default: 22): " port
#Create variables based on information passed
key_filename="$hostname""_id"
key_filepath="$HOME/.ssh/$key_filename"
#Gather flags for ssh key creation
# defaults
alg_flags="-t ed25519"
# responses
key_pass="n"
rsa="n"
# Passphrase?
read -r -p "Do you want to use a passphrase with this key? y/n (default: n): " key_pass
# What algorithm?
read -r -p "Do you want to use a legacy RSA 4096-bit key? Otherwise a modern ed25519 key will be used. y/n (default: n): " rsa
if [[ "$rsa" == "y" || "$rsa" == "Y" ]]; then
alg_flags="-t rsa -b 4096"
fi
# using a variable to hold the flag '-N ""' was causing issues
if [[ "$key_pass" == "y" || "$key_pass" == "Y" ]]; then
ssh-keygen $alg_flags -C "$email" -f "$key_filepath"
else
ssh-keygen $alg_flags -C "$email" -N "" -f "$key_filepath"
fi
keygen_status=$?
#If the key was created successfully echo the host info to the config file
#Give the user some info and copy to the remote machine.
if [ $keygen_status -eq 0 ]; then
# TODO: Make this IF more maintainable
if [[ "$port" != "" ]]; then
echo "
Host $shortname
User $remoteuser
HostName $hostname
Port $port
IdentityFile $key_filepath
VisualHostKey yes" >> $ssh_config_path
else
echo "
Host $shortname
User $remoteuser
HostName $hostname
IdentityFile $key_filepath
VisualHostKey yes" >> $ssh_config_path
fi
echo -e "=== Key generation complete! o——m ===";
echo ""
auto_copy="n"
read -r -p "Do you wish to attempt to copy the file over? (Will not work if password logins have been disabled) y/n (default: n) " auto_copy
if [[ "$auto_copy" == "y" || "$auto_copy" == "Y" ]]; then
echo "Now attempting to copy key over..."
ssh-copy-id -i "$key_filepath.pub" $remoteuser@$hostname
copy_result=$?
if [ $copy_result -eq 0 ]; then
echo "SSH key setup complete!";
exit 0;
else
echo "ERROR: An error occurred copying the key to the remote server."
echo "Try again manually."
exit $copy_result
fi
else
echo ""
echo "Key contents for easy copy and paste (see above for file path):"
cat "$key_filepath.pub"
exit 0
fi
else
echo "Error with key generation, exiting with status code.";
exit $keygen_status;
fi