#!/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()