#!/usr/bin/env python3
# Wrapper for /usr/bin/sbsign. This is specifically designed for the Rocky Linux
# Release Engineering team (SIG/Core) for the purpose of determining the correct
# slot to use from the HSM.
#
# Written for python 3.6 compatibility.
#
# Written by: Louis Abel <label@rockylinux.org>

import os
import sys
import argparse
import subprocess
import configparser

parser = argparse.ArgumentParser(
        description='Wrapper for sbsigntools',
        epilog='Use this as a way to point to the right HSM slots')

parser.add_argument('-c', '--cert', help='Certificate', required=True)
parser.add_argument('-i', '--input', help='Input file to sign', required=True)
parser.add_argument('-o', '--output', help='Output of signed file', required=True)
parser.add_argument('-r', '--release', help='Release version', required=True)

args = parser.parse_args()

def slot_machine(grabber):
    """
    Slot machine. Returns a slot.
    """
    # Extract the file name without the path and extension
    file_name = grabber.split('/')[-1].split('.')[0]
    config = configparser.ConfigParser()
    config.read("/yubihsm/sbslots.ini")

    # Try to retrieve the slot from the config using the file name
    returner = config.get("slots", file_name, fallback=None)

    if not returner:
        print('No valid key slot found.', file=sys.stderr)
        sys.exit(1)

    return returner

def run_signer(command):
    """
    Run the signer
    """
    command = ' '.join(command)
    try:
        if sys.version_info <= (3, 7):
            processor = subprocess.run(args=command, check=False,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       universal_newlines=True, shell=True)
        else:
            processor = subprocess.run(args=command, check=False, capture_output=True,
                                       text=True, shell=True)
    except Exception as badstuff:
        print(f'Command failed: {badstuff}', file=sys.stderr)
        sys.exit(1)

    print(command)
    print(processor.stdout)
    print(processor.stderr)
    sys.exit(processor.returncode)

def main():
    """
    Main function entrypoint
    """
    cert_slot = slot_machine(args.cert)
    engine_path = f'/yubihsm/rl{args.release}.conf'
    generate_command = [
            f'OPENSSL_CONF={engine_path}',
            'sbsign',
            '--engine',
            'pkcs11',
            '--key',
            f"'pkcs11:token=YubiHSM;id={cert_slot}'",
            '--cert',
            f'{args.cert}',
            f'{args.input}',
            '--output',
            f'{args.output}'
    ]
    run_signer(generate_command)

if __name__ == '__main__':
    main()
