#!/usr/bin/env python

#
# Copyright 2018 VMware, Inc.  All rights reserved. -- VMware Confidential
#
"""
Patch script that does the following:
1) Create 'vSphere Client solution user' role if doesn't exist with the privileges from roles.xml.
2) If 'vSphere Client solution user' role exists check update with all the privileges with roles.xml.


Assumptions:
1) roles.xml file should contain all the required privileges.
"""
import codecs
import logging
import os
import re
import sys
import warnings


sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
from .base import PatchBase
from l10n import localizedString, msgMetadata as _T
from distutils.version import LooseVersion
from cis.cisreglib import AuthzClient, CisregOptionParser, \
    LookupServiceClient, SsoClient, VmafdClient, _get_syscfg_info
from cis.vecs import Service, cli_path, vmafd_machine_id
from cis.utils import run_command, FileBuffer
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__))
from fss_utils import getTargetFSS


AUTHZ_TYPE_ID = 'cs.authorization'
EP_AUTHZ_PROTOCOL = 'vmomi'
EP_AUTHZ_TYPE_ID = 'com.vmware.cis.authorization.server'
VSPHERE_CLIENT_AUTHZ_ROLE = 'vSphere Client Solution User'
MACHINE_NAME = 'machine'
VSPHERE_CLIENT_ROLE_ID=1003
PATCH_VERSION = '1'
H5_CLIENT_SOLUTION_USER = "vsphere-webclient"
COMPONENT_NAME = "vsphere-ui"

logger = logging.getLogger(__name__)

class Patch3(PatchBase):
    """
    'vSphere Client Solution User' creation or modification with new privileges.
    """

    def __init__(self):
        """
        Constructor
        Set the patch version and summary.
        """

        version = LooseVersion("6.8.1.9999999")
        summary = localizedString(_T(
                "vsphere.ui.patch03.summary",
                "This patch facilitates 'vSphere Client Solution User' role creation or modification with new privileges"))
        PatchBase.__init__(self, version, summary)

    def do_patching(self, patch_context):
        logger.info("patch03_vsphere-ui patch for creating or modifying 'vsphere Client Solution User': being executed %s", patch_context)
        self.create_vsphere_client_solution_user_role_and_assign()

    def create_vsphere_client_solution_user_role_and_assign(self):
        logger.info('patch03_creating vSphere Client Solution User role and assigning to vsphere-webclient solution user')
        vmafdClient = vmafdpy3.client('localhost')
        username = vmafdClient.GetMachineName()
        password = vmafdClient.GetMachinePassword()
        machine_id = vmafd_machine_id()
        local_nodeid = vmafdClient.GetLDU()
        logger.info('patch03_create_vsphere_client_solution_user_role_and_assign -The LDU is '+ local_nodeid)
        solution_user_id = '%s-%s' % (H5_CLIENT_SOLUTION_USER, machine_id)
        logger.info('patch03_create_vsphere_client_solution_user_role_and_assign -Connecting to Lookup Service')
        ls_url, domain_name = _get_syscfg_info()
        ls_obj = LookupServiceClient(ls_url, retry_count=1)
        logger.info('patch03_create_vsphere_client_solution_user_role_and_assign - Getting STS endpoint')
        sts_url, sts_cert_data = ls_obj.get_sts_endpoint_data()
        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=local_nodeid)
        vsphereclient_roles_xml_file = '%sroles.xml' % self.get_roles_file_dir()
        cisreg_options = {'permission.newRole': vsphereclient_roles_xml_file}

        roles_buff = FileBuffer()
        roles_buff.readFile(vsphereclient_roles_xml_file)
        changed = False
        if not getTargetFSS("OAUTH2_LOGON"):
            roles_buff.findAndReplace("<privilegeId>VcIdentityProviders.Read</privilegeId>", "")
            changed = True
        if changed:
           roles_buff.writeFile(vsphereclient_roles_xml_file)

        cisreg_optparser = CisregOptionParser(cisreg_options)
        logger.info('patch03_create_vsphere_client_solution_user_role_and_assign -Logging into Authz')
        authz_client = AuthzClient(authz_endpoints[0].url, sso_client)
        role_obj = authz_client.get_role(role_id=VSPHERE_CLIENT_ROLE_ID)
        if role_obj is None:
           logger.info('patch03_create_vsphere_client_solution_user_role_and_assign -Creating vSphere Client Solution User role in Authz')
           authz_client.load_roles(cisreg_optparser.get_roles())
           logger.info('patch03_create_vsphere_client_solution_user_role_and_assign - Assigning vSphere Client Solution User role to vsphere-webclient solution user')
           authz_client.set_permission(domain_name, VSPHERE_CLIENT_AUTHZ_ROLE,solution_user_id,is_group=False)

        else:
           logger.info('patch03_create_vsphere_client_solution_user_role_and_assign -Updating vSphere Client Solution User role in Authz')
           role_data_list = cisreg_optparser.get_roles()
           for role_data in role_data_list:
               if int(role_data['id']) == VSPHERE_CLIENT_ROLE_ID:
                   authz_client.update_role(role_id=VSPHERE_CLIENT_ROLE_ID, priv_ids=role_data['priv_ids'])
                   break

        sso_client.cleanup()

    def get_roles_file_dir(self):
        return '/etc/vmware/%s/firstboot/' % COMPONENT_NAME