Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/scripts/ssh_host_keys_freeze.py
Views: 275
1
#!/usr/bin/env python3
2
# coding: utf8
3
# Author: Harald Schilly <[email protected]>
4
# Copyright: GPL3
5
"""
6
When a server in the GCE environment is started with a new IP and a new instance ID,
7
the host SSH keys in /etc/ssh are recreated.
8
That's in general a nice security feature, but this also happens when the instance type
9
changes (some scripts can change pre-empt to non-pre-empt boxes causing this, etc.).
10
11
This script hardcodes the current four /etc/ssh/ key-pairs in a config file for cloud-init.
12
This cloud-init is part of Ubuntu and managing a couple of things in the VM (hostname, network, etc.)
13
The generated config file then contains the key-pairs and on each boot they are used for writing
14
the keys.
15
16
So, the output in `/etc/cloud/cloud.cfg.d/99-smc.cfg` is like:
17
18
```
19
ssh_keys:
20
dsa_private: |
21
-----BEGIN DSA PRIVATE KEY-----
22
MIIBugIBAAKBgQD…
23
24
25
-----END DSA PRIVATE KEY-----
26
27
dsa_public: "ssh-dss AAA………"
28
```
29
30
Documentation:
31
http://cloudinit.readthedocs.org/en/latest/index.html
32
"""
33
import sys
34
import os
35
from os.path import join, basename, dirname, exists
36
from glob import glob
37
from pwd import getpwnam
38
39
out_fn = '/etc/cloud/cloud.cfg.d/99-smc.cfg'
40
41
try:
42
import yaml
43
except:
44
print(
45
"ERROR: I need yaml for python3, i.e. sudo apt-get install -y python3-yaml"
46
)
47
sys.exit(1)
48
49
50
class literal(str):
51
pass
52
53
54
def literal_presenter(dumper, data):
55
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
56
57
58
yaml.add_representer(literal, literal_presenter)
59
60
61
def main():
62
# hold key data, dict for key_type_public/key_type_private for each key_type
63
keys = {}
64
65
for key_fn in glob('/etc/ssh/ssh_host_*_key'):
66
key_type = basename(key_fn)[9:-4]
67
print("Reading key {}".format(key_type))
68
priv = open(key_fn).read()
69
publ = open(key_fn + ".pub").read()
70
keys[key_type + '_private'] = literal(priv)
71
keys[key_type + '_public'] = publ
72
73
out = yaml.dump({"ssh_keys": keys}, default_flow_style=False, width=10000)
74
# print(out)
75
76
if not exists(dirname(out_fn)):
77
raise Exception(
78
"Directory for {} does not exist. Are the clout-init utils installed?".
79
format(out_fn))
80
81
open(out_fn, 'w').write(out)
82
root = getpwnam("root")
83
os.chown(out_fn, root.pw_uid, root.pw_gid)
84
os.chmod(out_fn, 0o600)
85
86
87
if __name__ == '__main__':
88
try:
89
main()
90
except IOError as e:
91
raise e
92
print("You need to be root or prefix this with sudo")
93
94