5f4b5000c8
Previously if you ran `sshfp.py foo.opendev.org x.y.z.a` it would spit out records that look like: foo.opendev.org IN SSHFP 1 1 stuffstuffstuff The problem with this is when you copy this output into the zone file the lack of a terminating '.' means the record will actually be for foo.opendev.org.opendev.org. We address this by splitting on '.' and taking the first element. This will still be broken for hosts named foo.bar.opendev.org but for now is a decent improvement. Change-Id: Ib12f66c30e20a62d14d0d0ddd485e28f7f7ab518
65 lines
2.0 KiB
Python
Executable File
65 lines
2.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import subprocess
|
|
|
|
def generate_sshfp_records(hostname, ip, local):
|
|
'''Given a hostname and and IP address, scan the IP address (hostname
|
|
not in dns yet) and return a bind string with sshfp records'''
|
|
|
|
if local:
|
|
p = ['ssh-keyscan', '-D', ip]
|
|
else:
|
|
# Handle being run via sudo which is the usual way
|
|
# this is run.
|
|
p = ['ssh', '-o', 'StrictHostKeyChecking=no',
|
|
'-i', '/root/.ssh/id_rsa',
|
|
'root@%s' % ip, 'ssh-keygen', '-r', ip]
|
|
|
|
s = subprocess.run(p,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE).stdout.decode('utf-8')
|
|
fingerprints = []
|
|
for line in s.split('\n'):
|
|
if not line:
|
|
continue
|
|
_, _, _, algo, key_type, fingerprint = line.split(' ')
|
|
# ssh-keygen on the host seems to return DSS/DSA keys, which
|
|
# aren't valid to log in and not shown by ssh-keyscan -D
|
|
# ... prune it.
|
|
if algo == '2':
|
|
continue
|
|
fingerprints.append(
|
|
(algo, key_type, fingerprint))
|
|
|
|
# sort by algo and key_type to keep it consistent
|
|
fingerprints = sorted(fingerprints,
|
|
key=lambda x: (x[0], x[1]))
|
|
|
|
ret = ''
|
|
first = True
|
|
dns_hostname = hostname.split('.')[0]
|
|
for f in fingerprints:
|
|
ret += '%s%s\t\tIN\tSSHFP\t%s %s %s' % \
|
|
("\n" if not first else '', dns_hostname, f[0], f[1], f[2])
|
|
first = False
|
|
return ret
|
|
|
|
|
|
def sshfp_print_records(hostname, ip, local=False):
|
|
print(generate_sshfp_records(hostname, ip, local))
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("hostname", help="hostname")
|
|
parser.add_argument("ip", help="address to scan")
|
|
parser.add_argument("--local", action='store_true',
|
|
help="Run keyscan locally, rather than via ssh")
|
|
args = parser.parse_args()
|
|
|
|
sshfp_print_records(args.hostname, args.ip, args.local)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|