-
Notifications
You must be signed in to change notification settings - Fork 4
/
configure-ssh.py
executable file
·147 lines (121 loc) · 5.57 KB
/
configure-ssh.py
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
#!/usr/bin/env python
# Written by [email protected]
"""%prog [options] host ...
%prog will configure password-less SSH to remote hosts.
Examples:
%prog -u root host1
This is the simplest usage. It will prompt for the password for root@host1.
When it is done, "ssh root@host1" should run without asking for a password.
%prog -u root host1 host2
Same as above but it will repeat for host1 and host2.
%prog -u root $(cat master.txt worker.txt)
Same as above but it will repeat for each host listed in the files master.txt and worker.txt.
%prog -u root -p mysecretpassword host1 host2
To avoid being prompted for a password, specify it with the -p option.
You must have sshpass installed for this to work.
Understand the risks of using sshpass before using this in a secure setting.
%prog -u user1 -U centos host1
When configuring password-less SSH, use the account centos@host1 to establish the
initial SSH connection. This will configure the ~/.ssh directory for user1@host1 to
allow password-less SSH to this account.
%prog -u user1 -U centos -s host1
Same as above but centos@host1 will use sudo to access user1@host1's home directory.
This is useful for cloud images where password-less SSH already exists for centos@host1 but
not other accounts.
%prog --help
View all options."""
import os
import optparse
import tempfile
import shutil
import os.path
def configure_ssh(host, user, password, configure_as_user, sudo, public_key_path, configure_as_identity, identity):
"""host can be IP, fqdn, or relative host name"""
# Use a dictionary to make it easy to build the various command strings.
p = {
'password': password,
'user': user,
'host': host,
'configure_as_user': configure_as_user,
'public_key_path': public_key_path,
'configure_as_identity': configure_as_identity,
'identity': identity,
}
if p['password']:
p['sshpass'] = 'sshpass -p "%(password)s" ' % p
else:
p['sshpass'] = ''
if not p['configure_as_user']:
p['configure_as_user'] = p['user']
if sudo:
p['sudo'] = 'sudo '
p['ssh_opt_tt'] = '-tt '
else:
p['sudo'] = ''
p['ssh_opt_tt'] = ''
# Note that when ssh -tt is used, read from stdin blocks. Therefore, use head -1 to prevent blocking.
p['remote_cmd'] = ((
'%(sudo)smkdir -p ~%(user)s/.ssh ' +
'; %(sudo)stouch ~%(user)s/.ssh/authorized_keys ' +
'; %(sudo)schmod 700 ~%(user)s/.ssh ' +
'; %(sudo)schown -R %(user)s ~%(user)s/.ssh ' +
'; %(sudo)schown -R :%(user)s ~%(user)s/.ssh ' +
'; %(sudo)schmod 600 ~%(user)s/.ssh/authorized_keys ' +
'; head -1 - | %(sudo)stee -a ~%(user)s/.ssh/authorized_keys')
% p)
p['ssh_cmd'] = '"%(remote_cmd)s"' % p
if p['configure_as_identity']:
p['ssh_opt_i'] = '-i %(configure_as_identity)s ' % p
else:
p['ssh_opt_i'] = ''
if p['identity']:
p['ssh_opt_i_test'] = '-i %(identity)s ' % p
else:
p['ssh_opt_i_test'] = ''
# Remove host from known_hosts file to avoid problems with IP address reuse
cmd = 'ssh-keygen -R %(host)s' % p
print('# %s' % cmd)
os.system(cmd)
# Configure password-less SSH
cmd = ((
'cat %(public_key_path)s ' +
'| %(sshpass)sssh -o StrictHostKeyChecking=no %(ssh_opt_tt)s%(ssh_opt_i)s%(configure_as_user)s@%(host)s %(ssh_cmd)s')
% p)
print('# %s' % cmd)
os.system(cmd)
# Test password-less SSH
cmd = 'ssh %(ssh_opt_i_test)s%(user)s@%(host)s "echo -n success: ; hostname"' % p
print('# %s' % cmd)
os.system(cmd)
def main():
parser = optparse.OptionParser(usage=__doc__)
parser.add_option('-u', '--user', action='append', dest='users',
help='target user on remote host')
parser.add_option('-U', '--configure-as-user', action='store', dest='configure_as_user',
help='configure using this user account on remote host')
parser.add_option('-k', '--public-key', action='store', dest='public_key', default='~/.ssh/id_rsa.pub',
help='id_rsa.pub key file to authorize')
parser.add_option('-i', '--identity', action='store', dest='identity', default='~/.ssh/id_rsa',
help='id_rsa private key file for local user that should be allowed to SSH into the remote host')
parser.add_option('-I', '--configure-as-identity', action='store', dest='configure_as_identity', default='~/.ssh/id_rsa',
help='configure using id_rsa private key file')
parser.add_option('-n', '--host', action='append', dest='hosts',
help='name of remote host (-n is optional)')
parser.add_option('-p', '--password', action='store', dest='password',
help='password of user on remote host (requires sshpass)')
parser.add_option('-s', '--sudo', action='store_true', dest='sudo',
help='use sudo on remote host')
options, args = parser.parse_args()
hosts = args
if options.hosts:
hosts += options.hosts
if not options.users or not hosts:
parser.error('Missing required parameters')
public_key_path = os.path.expanduser(options.public_key)
if not os.path.isfile(public_key_path):
parser.error('The public key file %s is missing. Use the command "ssh-keygen -t rsa -b 4096" to create a key pair.' % public_key_path)
for user in options.users:
for host in hosts:
configure_ssh(host, user, options.password, options.configure_as_user, options.sudo, public_key_path, options.configure_as_identity, options.identity)
if __name__ == '__main__':
main()