#!/usr/bin/env python

#
# Copyright 2017 VMware, Inc.  All rights reserved. -- VMware Confidential
#
"""
Patch script that does the following:
1) Create SyncUsers SSO group
2) Add hvc solution user to the SSO group
3) Create a SyncUsers role in Authz
4) Assign SyncUsers role to SyncUsers SSO group
5) Remove global permissions from hvc solution user

Assumptions:
1) hvc solution user already exists
"""
import codecs
import logging
import os
import re
import sys
import warnings

sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
from cis.cisreglib import AuthzClient, CisregOptionParser, \
    LookupServiceClient, SsoClient, VmafdClient, _get_syscfg_info
from cis.vecs import Service, SsoGroup, cli_path, vmafd_machine_id
from cis.utils import run_command
sys.path.append('/usr/lib/vmware-vmafd/lib64')

# Suppress warnings coming from vmafd and identity imports.
with warnings.catch_warnings():
    warnings.simplefilter('ignore', RuntimeWarning)
    import vmafdpy3
    from identity.vmkeystore import VmKeyStore

sys.path.append(os.path.dirname(__file__))
import utils

COMPONENT_NAME = 'hvc'
AUTHZ_TYPE_ID = 'cs.authorization'
EP_AUTHZ_PROTOCOL = 'vmomi'
EP_AUTHZ_TYPE_ID = 'com.vmware.cis.authorization.server'
SYNC_SSO_GROUP = 'SyncUsers'
SYNC_SSO_GROUP_DESC = 'Sync Users'
SYNC_AUTHZ_ROLE = 'SyncUsers'
MACHINE_NAME = 'machine'
PATCH_VERSION = '1'

logger = logging.getLogger(__name__)


def doPatching(ctx):
    logger.info("hvc patch: being executed %s", ctx)
    logger.info("Introduces SyncUsers SSO group & sets permissions.")
    vmafdClient = vmafdpy3.client('localhost')
    username = vmafdClient.GetMachineName()
    password = vmafdClient.GetMachinePassword()
    machine_id = vmafd_machine_id()
    solution_user_id = '%s-%s' % (COMPONENT_NAME, machine_id)
    create_sync_sso_group_and_add_soluser(username, password, solution_user_id)
    create_sync_role_and_assign(username, password, solution_user_id)
    utils.update_patch_version(PATCH_VERSION)


def create_sync_sso_group_and_add_soluser(username, password,
                                          solution_user_id):
    logger.info("Logging into SSO Admin")
    sso_group = SsoGroup(username, password)
    logger.info("Creating SSO group %s " % SYNC_SSO_GROUP)
    sso_group.create(SYNC_SSO_GROUP, SYNC_SSO_GROUP_DESC)
    logger.info("Adding %s to %s" % (solution_user_id, SYNC_SSO_GROUP))
    sso_group.add_user(SYNC_SSO_GROUP, solution_user_id)


def create_sync_role_and_assign(username, password, solution_user_id):
    logger.info("Connecting to Lookup Service")
    ls_url, domain_name = _get_syscfg_info()
    ls_obj = LookupServiceClient(ls_url, retry_count=1)
    logger.info("Getting STS endpoint")
    sts_url, sts_cert_data = ls_obj.get_sts_endpoint_data()

    logger.info("Logging into SSO AdminClient as machine solution user")
    cert = None
    key = None

    with VmKeyStore('VKS') as ks:
        ks.load(MACHINE_NAME)
        cert = ks.get_certificate(MACHINE_NAME)
        key = ks.get_key(MACHINE_NAME)

    sso_client = SsoClient(sts_url, sts_cert_data, None, None, cert=cert,
                               key=key)
    ls_obj.set_sso_client(sso_client)
    authz_endpoints = ls_obj.get_service_endpoints(
                       AUTHZ_TYPE_ID, ep_protocol=EP_AUTHZ_PROTOCOL,
                       ep_type=EP_AUTHZ_TYPE_ID, local_nodeid=None)
    cisreg_options = {'permission.newRole': '%s/roles.xml' % utils.get_config_dir()}
    cisreg_optparser = CisregOptionParser(cisreg_options)
    logger.info("Logging into Authz")
    authz_client = AuthzClient(authz_endpoints[0].url, sso_client)
    logger.info("Creating SyncUsers role in Authz")
    authz_client.load_roles(cisreg_optparser.get_roles())
    logger.info("Assigning SyncUsers role to SyncUsers SSO group")
    authz_client.set_permission(domain_name, SYNC_AUTHZ_ROLE, SYNC_SSO_GROUP,
                                is_group=True)
    logger.info("Removing global permissions from hvc solution user")
    authz_client.remove_global_permission(domain_name, solution_user_id,
                                          is_group=False)
    sso_client.cleanup()


def is_patch_needed():
    return utils.is_patch_needed(1) or not sync_users_exist()


def sync_users_exist():
    vmafdClient = vmafdpy3.client('localhost')
    username = vmafdClient.GetMachineName()
    password = vmafdClient.GetMachinePassword()
    cli = cli_path('dir-cli')
    cmd = [cli, 'group', 'list', '--name', 'SyncUsers', '--login', username]
    ret, _, stderr = run_command(cmd, stdin=password,
                                     encoding=sys.getfilesystemencoding())
    if ret == 0:
        logger.info("SyncUsers sso group exists")
        return True
    else:
        logger.info("SyncUsers sso group does not exists, apply this patch")
        return False
