/
secure_keys
executable file
·189 lines (162 loc) · 8.3 KB
/
secure_keys
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
#!/usr/bin/python3
'''
Script for managing security keys in RIAPS systems
Created on March 20, 2019
Arguments:
optional argument:
- ``-H | --hosts hostnames``: list of hostnames (comma separated), VM will be rekeyed
- ``-R | --roles rolenames``: list of roles (comma separated)
- ``-f riaps-hosts.conf`` : absolute path to a conf file containing desired host_string
- ``-A hostnames`` : list of hostnames (comma separated) to be added, VM will not bet rekeyed
- ``-i identity file`` : absolute path to a private key file used in an extant RIAPS system
- ``-p | --passwd `` : keep password enabled on remote nodes
If specific hostnames are not given, the command will be called for all hosts
listed in /etc/riaps/riaps_hosts.conf
@author: timkrentz
'''
import os
import sys
import shlex
import argparse
import site
import subprocess
pycom_privateKey = 'id_rsa.key'
pycom_publicKey = 'id_rsa.pub'
pycom_cert = 'x509.pem'
pycom_zmqCert = 'riaps-sys.cert'
pycom_keys_dir = '/etc/riaps'
pycom_ln_dir = '/usr/local/riaps/keys'
vm_privateKey = 'id_rsa'
vm_publicKey = pycom_publicKey
vm_keys_dir = '/home/riaps/.ssh'
def bash(cmd):
t = shlex.split(cmd)
print("=== "+str(t))
result = subprocess.run(t)
return result
def openKeyPerms():
#temporarily open private key and certs on VM, so that they can be moved to new RIAPS nodes
#note: private key name of 'id_rsa' used on VM, instead of id_rsa.key to allow automatic inclusion in ssh setup
# riaps-pycom uses
if os.path.isfile(f'{vm_keys_dir}/{vm_privateKey}'):
bash(f'sudo chmod 444 {vm_keys_dir}/{vm_privateKey}')
if os.path.isfile(f'{vm_keys_dir}/{pycom_cert}'):
bash(f'sudo chmod 444 {vm_keys_dir}/{pycom_cert}')
def closeKeyPerms():
#return tighter restrictions to private key and certs
if os.path.isfile(f'{vm_keys_dir}/{vm_privateKey}'):
bash(f'sudo chmod 400 {vm_keys_dir}/{vm_privateKey}')
if os.path.isfile(f'{vm_keys_dir}/{pycom_cert}'):
bash(f'sudo chmod 400 {vm_keys_dir}/{pycom_cert}')
def rekey_VM():
#save old keys and certs
if os.path.isfile(f'{vm_keys_dir}/{vm_publicKey}'):
bash(f'ssh-add -d {vm_keys_dir}/{vm_publicKey}')
os.rename(f'{vm_keys_dir}/{vm_publicKey}', f'{vm_keys_dir}/{vm_publicKey}.old')
if os.path.isfile(f'{vm_keys_dir}/{vm_privateKey}'):
os.rename(f'{vm_keys_dir}/{vm_privateKey}', f'{vm_keys_dir}/{vm_privateKey}.old')
if os.path.isfile(f'{vm_keys_dir}/{pycom_zmqCert}'):
os.rename(f'{vm_keys_dir}/{pycom_zmqCert}', f'{vm_keys_dir}/{pycom_zmqCert}.old')
if os.path.isfile(f'{vm_keys_dir}/{pycom_cert}'):
os.rename(f'{vm_keys_dir}/{pycom_cert}', f'{vm_keys_dir}/{pycom_cert}.old')
#generate new keys and certs
#privateKey name is id_rsa for VM and id_rsa.key for riaps-pycom, so keep id_rsa.key until remote nodes are updated
bash(f'riaps_gen_cert -o {vm_keys_dir}')
bash(f'cp {vm_keys_dir}/{pycom_privateKey} {vm_keys_dir}/{vm_privateKey}')
bash(f'chmod 400 {vm_keys_dir}/{vm_privateKey}')
#never used key
bash(f'rm {vm_keys_dir}/riaps.key')
#add private key to ssh agent for immediate use
bash(f'ssh-add {vm_keys_dir}/{vm_privateKey}')
#generate public key from private key, riaps_gen_cert creates a PEM/OpenSSH formated public key
# which does not work well with ssh-add
subprocess.run(f'ssh-keygen -y -f {vm_keys_dir}/{vm_privateKey} > {vm_keys_dir}/{vm_publicKey}',shell=True)
#add public key to authorized keys (to allow deploy to work on VM)
subprocess.run(f'cat {vm_keys_dir}/{vm_publicKey} >> {vm_keys_dir}/authorized_keys',shell=True)
#copy keys and certs to riaps/keys location
c = [
f'sudo cp {vm_keys_dir}/{vm_privateKey} {pycom_keys_dir}/{pycom_privateKey}',
f'sudo chown root:riaps {pycom_keys_dir}/{pycom_privateKey}',
f'sudo chmod 440 {pycom_keys_dir}/{pycom_privateKey}',
f'sudo rm -f {pycom_ln_dir}/{pycom_privateKey}',
f'sudo ln -s {pycom_keys_dir}/{pycom_privateKey} {pycom_ln_dir}/{pycom_privateKey}',
f'sudo cp {vm_keys_dir}/{vm_publicKey} {pycom_keys_dir}/{pycom_publicKey}',
f'sudo chown root:riaps {pycom_keys_dir}/{pycom_publicKey}',
f'sudo chmod 440 {pycom_keys_dir}/{pycom_publicKey}',
f'sudo rm -f {pycom_ln_dir}/{pycom_publicKey}',
f'sudo ln -s {pycom_keys_dir}/{pycom_publicKey} {pycom_ln_dir}/{pycom_publicKey}',
f'sudo cp {vm_keys_dir}/{pycom_zmqCert} {pycom_keys_dir}/{pycom_zmqCert}',
f'sudo chown root:riaps {pycom_keys_dir}/{pycom_zmqCert}',
f'sudo chmod 444 {pycom_keys_dir}/{pycom_zmqCert}',
f'sudo chmod 444 {vm_keys_dir}/{pycom_zmqCert}',
f'sudo rm -f {pycom_ln_dir}/{pycom_zmqCert}',
f'sudo ln -s {pycom_keys_dir}/{pycom_zmqCert} {pycom_ln_dir}/{pycom_zmqCert}',
f'sudo cp {vm_keys_dir}/{pycom_cert} {pycom_keys_dir}/{pycom_cert}',
f'sudo chown root:riaps {pycom_keys_dir}/{pycom_cert}',
f'sudo chmod 440 {pycom_keys_dir}/{pycom_cert}',
f'sudo chmod 440 {vm_keys_dir}/{pycom_cert}',
f'sudo rm -f {pycom_ln_dir}/{pycom_cert}',
f'sudo ln -s {pycom_keys_dir}/{pycom_cert} {pycom_ln_dir}/{pycom_cert}',
]
for cmd in c:
bash(cmd)
print("rekeyed development machine with newly generated keys and certificates.")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-H", "--hosts", default="", help="list of hostnames, comma separated, for a complete reconfiguration") # List of hostnames to used instead of system configured file
parser.add_argument("-R", "--roles", default="", help="list of roles, comma separated")
parser.add_argument("-f", dest='hostsFile', help="absolute path to riaps-hosts.conf")
parser.add_argument("-A", dest='addtlHosts', help="list of hostnames, comma separated, to add to a current configuration")
parser.add_argument("-i", dest='privateKeyPath', help="absolute path to pre-established RIAPS private key")
parser.add_argument("-v", "--validate", action='store_const', const=True, help="validate host names")
parser.add_argument("-p", "--passwd", action='store_true', help="keep password for remote nodes")
args = parser.parse_args()
fcmd = "fab"
fflag = "-f"
fpaths = [p + "/riaps/" for p in site.getsitepackages()] + [os.getenv('RIAPSHOME')]
rekeyVM = True
if args.hosts:
fhosts = ("--hosts=" + args.hosts)
elif args.addtlHosts:
fhosts = ("--hosts=" + args.addtlHosts)
# Do not rekey VM if just adding additional hosts
rekeyVM = False
else:
fhosts = ""
froles = ("--roles=" + args.roles) if args.roles else ""
fhostsFile = ("--set hostsFile=" + args.hostsFile) if args.hostsFile else ""
fident = "-i "+ args.privateKeyPath \
if args.privateKeyPath and os.path.isfile(args.privateKeyPath) else ""
fvalidate = "--set validate" if args.validate else ""
fsyscheck = "sys.check"
fupdate = "riaps.updateNodeKey:%s" % args.passwd
fpath = None
for p in fpaths:
if p is None: continue
fp = os.path.join(p,"fabfile","")
if os.path.isdir(fp):
fpath = fp; break
if fpath is not None:
# Make sure RIAPS nodes are available first
print("Validating host availability: {}".format(args.hosts))
cmd = str.join(' ',(fcmd, fflag, fpath, fsyscheck, fhostsFile, fhosts, froles, fvalidate, fident))
p = bash(cmd)
if p.returncode != 0:
print("Unable to find hosts, aborting update process now ...")
sys.exit(-1)
if rekeyVM:
print("Rekeying VM")
rekey_VM()
# Rekey remote hosts
print("Rekeying hostnames: {}".format(args.hosts))
cmd = str.join(' ',(fcmd, fflag, fpath, fupdate, fhostsFile, fhosts, froles, fvalidate, fident))
bash(f'ssh-add {vm_keys_dir}/{vm_privateKey}.old')
openKeyPerms()
bash(cmd)
closeKeyPerms()
bash(f'ssh-add -d {vm_keys_dir}/{vm_publicKey}.old')
print("Rekeyed remote RIAPS nodes with development machine keys and certificates.")
# Remove id_rsa.key (a copy of id_rsa) from VM no longer needed
bash(f'rm {vm_keys_dir}/{pycom_privateKey}')
else:
print('RIAPS Fabfile is not installed, please update the riaps-pycom installation.')