#!/usr/bin/env python3

# Authors:
#     Dinesh Prasanth M K <dmoluguw@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the Lesser GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
#  along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright (C) 2018 Red Hat, Inc.
# All rights reserved.


"""
Script that prompts user for password during server startup
and store them on user's keyring
"""

import getopt
import logging
import os
import subprocess
import sys

import pki.server
import pki.server.instance

from pki.keyring import Keyring

logger = logging.getLogger(__name__)

logging.basicConfig(format='%(levelname)s: %(message)s')

tags = set()

# Create a instance of Keyring
keyring = Keyring()


def split_entries(entry):
    return entry.split(',')


def print_help():
    print('Usage: pki-server-nuxwdog [OPTIONS]')
    print()
    print('      --clear                Clear values stored in keyring.')
    print('      --help                 Show help message.')
    print()


try:
    opts, _ = getopt.gnu_getopt(sys.argv, '', ['clear', 'help'])

except getopt.GetoptError as e:
    logger.error(e)
    print_help()
    sys.exit(1)

for o, a in opts:

    if o == '--clear':
        keyring.clear_keyring()
        sys.exit()

    elif o == '--help':
        print_help()
        sys.exit()

    else:
        logger.error('option %s not recognized', o)
        print_help()
        sys.exit(1)

# 1. Get <instance> name from env variable NAME set in systemd unit file
instance_name = os.getenv('NAME', 'pki-tomcat')

# 2. Gather list of passwords required
# cms.tokenList, cms.passwordList --> For each subsystem in the <instance>

# Load the instance
instance = pki.server.instance.PKIInstance(instance_name)
instance.load()

subsystems = instance.subsystems

tags.add('internal')

for subsystem in subsystems:
    if 'cms.passwordlist' in subsystem.config:
        password_list = split_entries(subsystem.config['cms.passwordlist'])
        tags.update(password_list)

    if 'cms.tokenList' in subsystem.config:
        token_list = split_entries(subsystem.config['cms.tokenList'])

        # HSM token requires a prefix 'hardware-'
        for token in token_list:
            tags.add('hardware-' + token)

# 3a. Prompt the user using systemd-ask-password
# 3b. Store the values in the keyring using keyctl

for tag in sorted(iter(tags)):
    if tag.startswith('hardware-'):
        prompt_tag = tag[9:]
    else:
        prompt_tag = tag

    prompt = '[' + instance_name + '] Please provide the password for ' + prompt_tag + ':'

    cmd_ask_password = ['systemd-ask-password', prompt]

    entered_pass = subprocess.check_output(cmd_ask_password)

    key_name = instance_name + '/' + tag

    keyring.put_password(key_name=key_name, password=entered_pass)

# 4. Put this script to sleep in background to keep the keyring fd open until main program starts
# due to systemd bug #1668954
subprocess.Popen(['/usr/bin/sleep', '10'])
