is_known_as known_hosts metadata
This commit is contained in:
parent
637ab05590
commit
fe884f446a
4 changed files with 30 additions and 12 deletions
|
@ -66,12 +66,13 @@ files = {
|
|||
],
|
||||
},
|
||||
'/etc/ssh/ssh_known_hosts': {
|
||||
'content': '\n'.join(
|
||||
repo.libs.ssh.known_hosts_entry_for(other_node)
|
||||
for other_node in sorted(repo.nodes)
|
||||
'content': '\n'.join(sorted(
|
||||
line
|
||||
for other_node in repo.nodes
|
||||
if other_node != node
|
||||
and other_node.has_bundle('ssh')
|
||||
) + '\n',
|
||||
for line in other_node.metadata.get('ssh/is_known_as')
|
||||
)) + '\n',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from base64 import b64decode
|
|||
defaults = {
|
||||
'ssh': {
|
||||
'multiplex_incoming': True,
|
||||
'is_known_as': set(), # known_hosts for other nodes
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,7 @@ def host_key(metadata):
|
|||
def hostnames(metadata):
|
||||
ips = set()
|
||||
|
||||
for network in node.metadata.get('network').values():
|
||||
for network in metadata.get('network').values():
|
||||
if network.get('ipv4', None):
|
||||
ips.add(str(ip_interface(network['ipv4']).ip))
|
||||
if network.get('ipv6', None):
|
||||
|
@ -55,7 +56,7 @@ def hostnames(metadata):
|
|||
|
||||
domains = {
|
||||
domain
|
||||
for domain, records in node.metadata.get('dns').items()
|
||||
for domain, records in metadata.get('dns').items()
|
||||
for type, values in records.items()
|
||||
if type in {'A', 'AAAA'}
|
||||
and set(values) & ips
|
||||
|
@ -70,3 +71,18 @@ def hostnames(metadata):
|
|||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@metadata_reactor.provides(
|
||||
'ssh/is_known_as',
|
||||
)
|
||||
def is_known_as(metadata):
|
||||
return {
|
||||
'ssh': {
|
||||
'is_known_as': repo.libs.ssh.known_hosts_entry_for(
|
||||
node_id=metadata.get('id'),
|
||||
hostnames=tuple(sorted(metadata.get('ssh/hostnames'))),
|
||||
pubkey=metadata.get('ssh/host_key/public'),
|
||||
),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ from os.path import expanduser
|
|||
def apply_start(repo, target, nodes, interactive=False, **kwargs):
|
||||
with open(expanduser('~/.ssh/known_hosts_ckn'), 'w+') as file:
|
||||
file.write('\n'.join(sorted(
|
||||
repo.libs.ssh.known_hosts_entry_for(node)
|
||||
line
|
||||
for node in repo.nodes
|
||||
if node.has_bundle('ssh')
|
||||
for line in node.metadata.get('ssh/is_known_as')
|
||||
|
||||
)))
|
||||
|
|
|
@ -55,18 +55,17 @@ def generate_ed25519_key_pair(secret):
|
|||
# - take the salt from the ssh-ed25519 entry (first field after '|1|')
|
||||
# - `bw debug -c 'repo.libs.ssh.known_hosts_entry_for(repo.get_node(<node with hostname 10.0.0.5>), <salt from ssh-keygen>)'`
|
||||
@cache
|
||||
def known_hosts_entry_for(node, test_salt=None):
|
||||
def known_hosts_entry_for(node_id, hostnames, pubkey, test_salt=None):
|
||||
lines = set()
|
||||
|
||||
for hostname in sorted(node.metadata.get('ssh/hostnames')):
|
||||
for hostname in hostnames:
|
||||
if test_salt:
|
||||
salt = b64decode(test_salt)
|
||||
else:
|
||||
salt = sha1((node.metadata.get('id') + hostname).encode()).digest()
|
||||
salt = sha1((node_id + hostname).encode()).digest()
|
||||
|
||||
hash = hmac.new(salt, hostname.encode(), sha1).digest()
|
||||
pubkey = node.metadata.get('ssh/host_key/public')
|
||||
|
||||
lines.add(f'|1|{b64encode(salt).decode()}|{b64encode(hash).decode()} {" ".join(pubkey.split()[:2])}')
|
||||
|
||||
return '\n'.join(sorted(lines))
|
||||
return lines
|
||||
|
|
Loading…
Reference in a new issue