Esempio n. 1
0
    def _execute_api(self, *args):
        """Instantiate and execute script called by API."""
        # split arguments as needed

        args, kwargs = args
        method, endpoint = args
        endpoint_key = kwargs['endpoint_key'].split(':')[1]

        # identify what might be a query to the API.
        if '?' in endpoint:
            endpoint, query = endpoint.split('?')
        else:
            query = ''

        # Get endpoint doc
        api = self.meta_api.doc['paths'][endpoint_key][method]

        # Treat source to be a importable path.
        if '/' in api['source']:
            source = api['source'].split('/')
        elif '\\' in api['source']:
            source = api['source'].split('\\')
        else:
            source = api['source'].split()

        source = source[:-1]
        source = '/'.join(source)

        # Import it.
        sys.path.append(source)
        mio_commando = importlib.import_module(api['operation'])

        # Instanciate the Class.
        myoperation = getattr(mio_commando, api['operationId'])
        myoperation_inst = myoperation(self.cbacker, self.rbkcli_logger)
        #myoperation_inst = myoperation(self.cbacker)

        # Attribute the parameters to be passed to script.
        if kwargs['data'] == {}:
            data = {}
        else:
            data = json.loads(kwargs['data'])
        data = DotDict(data)
        pass_args = DotDict({
            'parameters': data,
            'query': kwargs['params'],
            'method': args[0],
            'endpoint': args[1],
            'target': self.target
        })

        # Return class execution
        try:
            result = myoperation_inst.execute(pass_args)
        except AttributeError as error:
            msg = 'Error executing custom script, please debug it... ' + str(
                error)
            raise RbkcliException.ApiHandlerError(msg + '\n')

        return json.dumps(result, indent=2)
Esempio n. 2
0
    def call_back(self, args):
        """Perform same level of parsing (even CLI) as any other request."""
        self.request, self.args = self.parseit(args)
        self.stct_request = self.structreit(self.args, self.request)

        result = DotDict()
        result.text = self.callit(self.stct_request)
        result.status_code = 200
        result.text = json.dumps(result.text, indent=2)

        return self.formatter.outputfy(self.req, result)
Esempio n. 3
0
    def __init__(self, logger, conf_dict=None, workflow='command'):
        """Initialize the tools."""
        self.logger = logger
        self.ssh_conn = False
        self.called_tools = []
        self.workflow = workflow
        self.auth = DotDict({})
        self.auth_dict = {}

        if conf_dict is None:
            conf_dict = {}
        self.conf_dict = conf_dict
Esempio n. 4
0
    def __init__(self, logger, auth, version, user_profile='admin'):
        """Initialize Rbkcli Executor."""
        self._verify_api_version(version)
        self.local_tools = DotDict({})
        self.local_tools.logger = logger
        self.local_tools.auth = auth
        self.local_tools.user_profile = user_profile

        self.version = version

        self.endpoints = {}
        self._assign_methods()
        self.filter_lists = DotDict({})
        self.focus_list = []
Esempio n. 5
0
    def structreit(self, args, request):
        """Reestructure arguments provided."""
        self.args = args
        self.request = {}
        requet_1 = {}
        for key in request.keys():
            self.request[key] = request[key]
            requet_1[key] = request[key]

        # Structure the request to the needed format.
        stct_request = self.base_kit.parser.create_request_structure(
            requet_1, self.args)

        # Pass data to dot dictionary
        self.stct_request = DotDict()
        for key in stct_request.keys():
            self.stct_request[key] = stct_request[key]

        # Normalizing request dictionary
        self.stct_request.endpoint = ' '.join(self.stct_request.api_endpoint)
        self.stct_request.formatt = 'raw'
        self.stct_request.param = self.stct_request.query
        self.stct_request.data = self.stct_request.parameter
        self.stct_request.structured = True

        return self.stct_request
Esempio n. 6
0
    def load_auth(self):
        """Load authentication."""
        self.called_tools.append('load_auth')
        try:
            self.auth = self.load_file_auth()
        except RbkcliException.ToolsError:
            try:
                self.auth = self.load_env_auth()
            except RbkcliException.ToolsError:
                self.auth = DotDict({})

        # Change the verification for target verification, auth verification
        # # To be performed before API execution.
        if not self._verify_target_consistency(self.auth):
            raise Exception('Verify auth code')

        return self.auth
Esempio n. 7
0
 def __init__(self, logger, user_profile, auth=None):
     """Initialize API requester."""
     self.logger = logger
     self.auth = auth
     if auth is None:
         self.auth = {}
     self.url = ''
     self.api_result = requests.Response()
     self.user_profile = user_profile
     self.auth_prpt = DotDict()
     self.auth_prpt.type_ = ''
     self.auth_prpt.header = ''
     self.auth_prpt.primary_exception = ''
Esempio n. 8
0
 def __init__(self, user_profile='config', base_folder='', auth=None):
     """Initialize CLI helper."""
     # Instantiate CLI target
     self.ops = []
     self.ops_v = []
     self.args = []
     self.incomplete = ''
     self.result = []
     self.rbk_target = None
     self.ctx = DotDict()
     self.ctx.user_profile = user_profile
     self.ctx.base_folder = base_folder
     self.auth = auth
Esempio n. 9
0
 def __init__(self, logger, user_profile, auth=None):
     """Initialize API requester."""
     self.logger = logger
     self.auth = auth
     if auth is None:
         self.auth = {}
     self.url = ''
     self.api_result = requests.Response()
     self.user_profile = user_profile
     self.auth_prpt = DotDict()
     self.auth_prpt.type_ = ''
     self.auth_prpt.header = ''
     self.auth_prpt.primary_exception = ''
     self.python_version = sys.version.split("(")[0].strip()
     self.rbkcli_version = '1.0.0b4'
Esempio n. 10
0
    def _iteration_context(self, definitions, json_data):
        """Define the context to use during iteration."""
        self.cursor = ''

        # Create dictionary to save all maps and make it accessible.
        self.map = DotDict({})
        self.map.full = []
        self.data_tag = False

        # Fix by unifying variables and removing redundant
        self.level = 0

        # Json Keys that will be ignored while creating the map.
        # the following keys are a sort of metadata presented by the
        # documentation, so we use them to accurately build a valid
        # representation of any response.
        self.excluded_fields = [
            'properties', 'items', 'allOf', 'data', 'hasMore', 'total'
        ]
        self.exclude_properties = [
            'type', 'format', 'description', 'required', 'enum'
        ]

        # Get the schema of the response documentation only.
        try:
            json_dict = json_data['doc']['responses']['200']['schema']
        except KeyError:
            json_dict = {}
        # Translate datatypes from documentation to python json module.
        self.type_dict = {
            'string': 'str',
            'unicode': 'str',
            'boolean': 'bool',
            'integer': 'int',
            'empty': 'dict',
            'object': 'dict',
            'number': 'number',
            'array': 'list'
        }

        # Iterate json data creating the map
        result = self._iterate_json(json_dict)

        # Create map variations from metadata gathered
        self._gen_all_maps()

        # Return the map structure.
        return result
Esempio n. 11
0
 def __init__(self, call_backer, rbkcli_logger):
     """Initialize external scripts integration class."""
     self.rbkcli = call_backer
     self.rbkcli_logger = rbkcli_logger
     self.request = DotDict({
         'parameter': {},
         'filter': None,
         'version': '',
         'context': None,
         'table': False,
         'select': None,
         'list': False,
         'query': '',
         'method': 'post',
         'api_endpoint': [],
         'loop': None,
         'pretty_print': False,
         'info': False,
         'documentation': False
     })
Esempio n. 12
0
class RubrikApiHandler:
    """Define methods to execute the APIs."""
    def __init__(self, logger, auth, version, user_profile='admin'):
        """Initialize Rbkcli Executor."""
        self._verify_api_version(version)
        self.local_tools = DotDict({})
        self.local_tools.logger = logger
        self.local_tools.auth = auth
        self.local_tools.user_profile = user_profile

        self.version = version

        self.endpoints = {}
        self._assign_methods()
        self.filter_lists = DotDict({})
        self.focus_list = []

    def _verify_api_version(self, version):
        """Verify the provided API version."""
        if version not in CONSTANTS.SUPPORTED_API_VERSIONS:
            msg = str('API version [' + version + '] does not match any '
                      'accepted version.')
            error = 'ApiHandlerError # ' + msg
            self.local_tools.logger.error(msg)
            raise RbkcliException.ApiHandlerError(error)

    def _assign_methods(self):
        """Assign the correct import and execute method based in version."""
        if self.version in ('v1', 'v2', 'internal'):
            self.import_api = self._download_api_doc
            self.execute_api = self.api_requester
        else:
            self.import_api = self._temp_import

    def _download_api_doc(self):
        """Download the swagger api-doc file from server."""
        try:
            url = str('https://%s/docs/%s/api-docs' %
                      (self.local_tools.auth.server, self.version))
            tmp_tools = RbkcliTools(self.local_tools.logger)
            content = tmp_tools.download_file(url)
            content_dict = tmp_tools.yaml_load(content)
            self.endpoints = {
                'paths': content_dict['paths'],
                'definitions': content_dict['definitions']
            }
        except RbkcliException.ToolsError as error:
            msg = '%s [%s]. %s' % ('ApiHandlerError # Unable to download API',
                                   self.version, error)
            self.local_tools.logger.error(msg)

        return self.endpoints

    def api_requester(self, *args, **kwargs):
        """Instantiate requester and request API."""
        method, endpoint = args
        endpoint_key = kwargs['endpoint_key']
        data = kwargs['data']
        params = kwargs['params']

        if self.focus_list != [] and endpoint_key not in self.focus_list:
            msg = str('Requested endpoint [' + endpoint_key + '] not found on'
                      ' authorized endpoints list.')
            raise RbkcliException.ApiHandlerError(str(msg))

        endpoint = '/%s/%s' % (self.version, endpoint)
        api_rs = ApiRequester(self.local_tools.logger,
                              self.local_tools.user_profile,
                              auth=self.local_tools.auth).demand(method,
                                                                 endpoint,
                                                                 data=data,
                                                                 params=params)
        return api_rs

    def gen_authorization_lists(self):
        """
        Create custom lists of authorized based in the user profile.

        The focus list is used to verify if the API can be executed or not.
        """
        filter_list = self._create_all_methods_list(string='REQUIRES SUPPORT'
                                                    ' TOKEN')

        for user in CONSTANTS.USERS_PROFILE:
            self.filter_lists[user] = []
            requires = ''
            if user == 'admin':
                requires = 'NA'
            for method in CONSTANTS.SUPPORTED_USER_METHODS[user]:
                for method_line in filter_list:
                    if str(':%s:%s' % (method, requires)) in method_line:
                        self.filter_lists[user].append(method_line)

        for user, filter_list in self.filter_lists.items():
            filter_list.sort()

        self.focus_list = self.filter_lists[self.local_tools.user_profile]

    def _create_all_methods_list(self, field='summary', string='TOKEN'):
        """Generate simplified list of paths and methods."""
        filter_list = []
        string_ = string.replace(' ', '_')

        for endpoint, endpoint_data in self.endpoints['paths'].items():
            for method, method_data in endpoint_data.items():
                filter_list.append('%s:%s:%s:%s' %
                                   (self.version, endpoint, method, 'NA'))
                for doc_field, doc_field_data in method_data.items():
                    if field == doc_field and string in doc_field_data:
                        filter_list.remove(
                            '%s:%s:%s:%s' %
                            (self.version, endpoint, method, 'NA'))
                        filter_list.append(
                            '%s:%s:%s:%s' %
                            (self.version, endpoint, method, string_))
        return filter_list

    def _temp_import(self):
        """Place holder import for unpredicted API versions."""
        msg = 'ApiHandlerError # Api version not supported.'
        self.local_tools.logger.error(msg)
        return {}
Esempio n. 13
0
 def __init__(self, tools):
     """Initialize scripts customizer APIs class."""
     self.tools = tools
     # Define the path to search.
     self.meta_api = DotDict()
     self.scripts_folder = CONSTANTS.BASE_FOLDER + '/scripts'
Esempio n. 14
0
class RbkcliTools:
    """Define tools to be widely available throughout the code."""
    def __init__(self, logger, conf_dict=None, workflow='command'):
        """Initialize the tools."""
        self.logger = logger
        self.ssh_conn = False
        self.called_tools = []
        self.workflow = workflow
        self.auth = DotDict({})
        self.auth_dict = {}

        if conf_dict is None:
            conf_dict = {}
        self.conf_dict = conf_dict

    def load_yaml_file(self, yaml_file):
        """Open file as read, load yaml, returns dict."""
        self.called_tools.append('load_yaml_file')

        try:
            with open(yaml_file, 'r') as file:
                dict_result = yaml.safe_load(file.read())
        except FileNotFoundError as error:
            raise RbkcliException.ToolsError(error)

        return dict_result

    def load_json_file(self, json_file):
        """Open file as read, load json, returns dict."""
        self.called_tools.append('load_json_file')
        try:
            with open(json_file, 'r') as file:
                dict_result = json.load(file)
        except FileNotFoundError as error:
            self.safe_create_folder(CONSTANTS.CONF_FOLDER)
            raise RbkcliException.ToolsError(error)
        except json.decoder.JSONDecodeError as error:
            raise RbkcliException.ToolsError(error)

        return dict_result

    def create_yaml_file(self, yml_dict, yml_file):
        """Open file as write, dump yaml dict to file."""
        self.called_tools.append('create_yaml_file')
        try:
            with open(yml_file, 'w') as file:
                yaml.dump(yml_dict, file, default_flow_style=False)
            self.logger.debug('File created successfully: ' + yml_file)

            return True
        except FileNotFoundError as error:
            error = str(error) + '\n'
            msg = 'Exception is ' + error
            self.logger.error('IOToolsError # ' + msg)
            return False

        except Exception as error:
            error = str(error) + '\n'
            msg = 'Exception is ' + error
            self.logger.error('IOToolsError # ' + msg)
            raise RbkcliException.ToolsError(error)

    def create_json_file(self, json_dict, json_file):
        """Open file as write, dump json dict to file."""
        self.called_tools.append('create_json_file')
        try:
            with open(json_file, 'w') as file:
                file.write(json.dumps(json_dict, indent=2, sort_keys=True))
            self.logger.debug('IOTools # File created successfully: ' +
                              json_file)
            return True
        except FileNotFoundError as error:
            error = str(error) + '\n'
            msg = 'Exception is ' + error
            self.logger.error('IOToolsError # ' + msg)
            return False

        except Exception as error:
            error = str(error) + '\n'
            msg = 'Exception is ' + str(error)
            self.logger.error('IOToolsError # ' + msg)
            raise RbkcliException.ToolsError(error)

    def safe_create_json_file(self, json_dict, json_file):
        """Open file as write, dump json dict to file."""
        if os.path.isfile(json_file):
            return False
        else:
            if not self.create_json_file(json_dict, json_file):
                return False
        return True

    def create_simple_swagger_file(self, data, file):
        """Create a swagger file, version 2, providing minimum data."""
        self.called_tools.append('create_simple_swagger_file')
        swagger_example = {
            'basePath': data['base_path'],
            'consumes': ['application/json'],
            'info': {
                'description': data['description'],
                'title': data['title'],
                'version': '1.0.0'
            },
            'paths': data['paths'],
            'produces': ['application/json'],
            'swagger': '2.0'
        }
        return self.create_yaml_file(swagger_example, file)

    def ssh_connection(self, server, username, password, port=22):
        """Create paramiko's SSH session with provided data."""
        self.called_tools.append('ssh_connection')
        self.ssh_conn = paramiko.SSHClient()
        self.ssh_conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh_conn.connect(server,
                              port=port,
                              username=username,
                              password=password)

        return self.ssh_conn

    def ssh_cmd(self, cmd, ssh_conn=None):
        """Execute ssh command using Paramiko exec_command() method."""
        self.called_tools.append('ssh_cmd')

        # If connection arg is not given use the instance ssh_con
        if ssh_conn == '':
            ssh_conn = self.ssh_conn

        # Declaring
        results = {}
        stdin, stdout, stderr = ssh_conn.exec_command(cmd)

        # Split session output in a dictionary
        name = ['stdin', 'stdout', 'stderr']
        for item in enumerate([stdin, stdout, stderr]):
            try:
                results[name[item[0]]] = item[1].readlines()
            except IOError:
                results[name[item[0]]] = 'Warning ## cant read content'

        return results

    def ssh_cmd_shell(self, cmd, ssh_conn=None):
        """Execute ssh command using Paramiko invoke_shell() method."""
        self.called_tools.append('ssh_cmd_shell')

        # Declaring
        results = []

        ssh_session = ssh_conn.invoke_shell()

        time.sleep(1)

        for command in cmd:
            ssh_session.send(command + '\n')
            time.sleep(2.5)
            data = ssh_session.recv(10000)
            data = data.decode('utf-8')
            data = data.strip().split('\n')
            results = results + data

        ssh_conn.close()

        return results

    def load_env_auth(self):
        """Load authentication data from environment variables."""
        self.called_tools.append('load_env_auth')
        try:
            self.auth.server = os.environ['rubrik_cdm_node_ip']
            self.auth.username = os.environ['rubrik_cdm_username']
            self.auth.password = os.environ['rubrik_cdm_password']
            self.auth.token = os.environ['rubrik_cdm_token']

        except KeyError as bad_key:
            if str(bad_key) != "\'rubrik_cdm_token\'" and str(
                    bad_key) != "\'RUBRIK_CDM_TOKEN\'":
                msg = '%s%s%s' % ('Unable to load environmental variable for'
                                  ' authentication: ', bad_key,
                                  '. Are they defined?')
                self.logger.error('IOToolsError # ' + msg)
                raise RbkcliException.ToolsError(msg)
            else:
                # Log successful actions
                keys = ''
                for line in self.auth.keys():
                    keys = keys + ',' + line
                msg = '%s [%s]' % ('IOTools # Successfully loaded'
                                   ' environmental vars', keys.strip(','))
                self.logger.debug(msg)

        return self.auth

    def load_conf_file(self, file='', conf_dict=None):
        """Load configuration data from json file."""
        self.called_tools.append('load_conf_file')
        if conf_dict is None:
            conf_dict = {}
        try:
            if file == '':
                file = CONSTANTS.CONF_FOLDER + '/rbkcli.conf'
            msg = '%s [%s]' % ('IOTools # Successfully loaded configuration'
                               ' file: ', file)
            if conf_dict == {} and self.conf_dict == {}:
                self.conf_dict = self.load_json_file(file)
                self.logger.debug(msg)
            elif isinstance(conf_dict, dict) and self.conf_dict == {}:
                self.conf_dict = conf_dict
                self.logger.debug(msg)
            else:
                msg = 'IOTools # Configuration file already loaded.'
                self.logger.debug(msg)
            CONSTANTS.CONF_DICT = self.conf_dict
        except RbkcliException.ToolsError:
            try:
                self.create_vanila_conf()
                self.load_conf_file()
            except RbkcliException.ToolsError:
                msg = 'Unable to load configuration file'
                self.logger.error('IOToolsError # ' + msg)
                raise RbkcliException.ToolsError(msg)
        return self.conf_dict

    def create_vanila_conf(self):
        """Create a default configuration file."""
        self.called_tools.append('create_vanila_conf')
        conf_dict = {
            "config": {
                "storeToken": {
                    "value":
                    "False",
                    "description":
                    str("Caches the last successful token "
                        "with environment data.")
                },
                "logLevel": {
                    "value":
                    "debug",
                    "description":
                    str("Verbosity of the logs written to the"
                        " file logs/rbkcli.log.")
                },
                "useCredentialsFile": {
                    "value":
                    "False",
                    "description":
                    str("Tries to load credentials from auth"
                        " file before looking for env vars.")
                },
                "credentialsFile": {
                    "value":
                    "target.conf",
                    "description":
                    str("File where to load credentials from, "
                        "before looking for env vars.")
                },
                "whiteList": {
                    "description":
                    "",
                    "value": [
                        'v1:/session:post:NA',
                        'internal:/report/{id}/table:post:NA',
                        'internal:/managed_volume/{id}/begin_snapshot:post:NA',
                        'internal:/managed_volume/{id}/end_snapshot:post:NA',
                        'internal:/support/support_bundle:post:NA',
                        'rbkcli:/cmdlet/profile:get:NA',
                        'rbkcli:/cmdlet/profile:post:NA',
                        'rbkcli:/cmdlet/sync:post:NA',
                        'rbkcli:/cmdlet:delete:NA', 'rbkcli:/cmdlet:get:NA',
                        'rbkcli:/cmdlet:post:NA', 'rbkcli:/commands:get:NA',
                        'rbkcli:/jsonfy:get:NA', 'rbkcli:/script/sync:post:NA',
                        'rbkcli:/script:get:NA', 'scripts:/log/bundle:post:NA'
                    ]
                },
                "blackList": {
                    "description": "",
                    "value": []
                },
                "userProfile": {
                    "description":
                    str("String value which can be admin or "
                        "support. A profile is a set of API"
                        " endpoints that is available in the"
                        " command line."),
                    "value":
                    "admin"
                }
            }
        }
        file = CONSTANTS.CONF_FOLDER + '/rbkcli.conf'
        try:
            self.safe_create_folder(CONSTANTS.CONF_FOLDER)
            self.create_json_file(conf_dict, file)
            msg = 'Successfully created new configuration file'
            self.logger.debug('IOTools # ' + msg)
        except Exception:
            msg = 'Unable to create new configuration file'
            self.logger.error('IOToolsError # ' + msg)
            raise RbkcliException.ToolsError(msg)

    def load_auth_file(self):
        """Load authentication data from json file."""
        self.called_tools.append('load_auth_file')
        file = 'rbkcli.conf'
        try:
            if self.conf_dict == {}:
                self.load_conf_file()
            file = self.conf_dict['config']['credentialsFile']['value']
            file = CONSTANTS.CONF_FOLDER + '/' + file
            self.auth_dict = self.load_json_file(file)
        except RbkcliException.ToolsError:
            msg = 'Unable to load auth file, [' + file + ']'
            self.logger.error('IOToolsError # ' + msg)
            raise RbkcliException.ToolsError(msg)

    def load_file_auth(self):
        """Load authentication data from json file."""
        self.called_tools.append('load_file_auth')

        if self.conf_dict['config']['useCredentialsFile']['value'] == 'False':
            msg = 'CredentialsFile is disable, unable to read from file.'
            raise RbkcliException.ToolsError(msg)

        self.load_auth_file()
        auth_keys = ['server', 'token', 'username', 'password']
        for key in auth_keys:
            self.load_auth_key(key)
        # Log successful actions
        keys = ''
        for line in self.auth.keys():
            keys = keys + ',' + line
        msg = '%s [%s]' % ('IOTools # Successfully loaded file auth data',
                           keys.strip(','))
        self.logger.debug(msg)

        return self.auth

    def load_auth_key(self, key):
        """Load key by key confirming if consistency is kept."""
        try:
            self.auth[key] = self.auth_dict[key]

        except KeyError as bad_key:
            if str(bad_key) == "\'token\'":
                if ('username' not in self.auth_dict.keys()
                        and 'password' not in self.auth_dict.keys()):
                    msg = '%s%s%s' % ('Unable to load authentication data from'
                                      ' configuration file: ', bad_key,
                                      '. Are all keys defined correctly?')
                    self.logger.error('IOToolsError # ' + msg)
                    raise RbkcliException.ToolsError(msg)

            elif (str(bad_key) != "\'password\'"
                  or str(bad_key) != "\'username\'"):
                msg = '%s%s%s' % ('Unable to load authentication data from '
                                  'configuration file: ', bad_key,
                                  '. Are all keys defined correctly?')
                self.logger.error('IOToolsError # ' + msg)
                raise RbkcliException.ToolsError(msg)

    def load_auth(self):
        """Load authentication."""
        self.called_tools.append('load_auth')
        try:
            self.auth = self.load_file_auth()
        except RbkcliException.ToolsError:
            try:
                self.auth = self.load_env_auth()
            except RbkcliException.ToolsError:
                self.auth = DotDict({})

        # Change the verification for target verification, auth verification
        # # To be performed before API execution.
        if not self._verify_target_consistency(self.auth):
            raise Exception('Verify auth code')

        return self.auth

    def _verify_target_consistency(self, auth):
        """Verify if minimum auth params has been provided."""
        self.auth = auth
        if 'server' in self.auth.keys():
            self.auth.server = self._resolve_target(self.auth.server)
            if (self.auth.server == ''
                    or not self.is_valid_ip_port(self.auth.server)):
                if self.workflow == 'command':
                    msg = 'Invalid or missing Rubrik server'
                    self.logger.error('AuthenticationError # ' + msg)
                    self.auth.server = self._user_input(
                        'Rubrik server IP: ', self.is_valid_ip_port)
        else:
            if self.workflow == 'command':
                msg = 'Invalid or missing authentication parameters.'
                self.logger.error('AuthenticationError # ' + msg)
                self.auth.server = self._user_input('Rubrik server IP: ',
                                                    self.is_valid_ip_port)
            elif self.workflow == 'complete':
                self.auth.server = ''
        return True

    def verify_auth_consistency(self, auth):
        """Verify if minimum auth params has been provided."""
        self.auth = auth

        # To Fix Clean
        if 'token' in self.auth.keys():
            if (self.auth.token == ''
                    or not self.is_valid_uuid(self.auth.token)):
                msg = 'Invalid or missing Rubrik token'
                self.logger.error('AuthenticationError # ' + msg)
                self.auth.token = self._user_input('Rubrik API token: ',
                                                   self.is_valid_uuid)
            else:
                pass

        if 'username' in self.auth.keys() and 'password' in self.auth.keys():
            if self.auth.username != '' and self.auth.password != '':
                pass
            elif self.auth.username == '':
                msg = 'Invalid or missing username/password'
                self.logger.error('AuthenticationError # ' + msg)
                self.auth.username = self._user_input('Rubrik username: '******'':
                print('password:'******'':
                msg = 'Invalid or missing password format'
                self.logger.error('AuthenticationError # ' + msg)
                self.auth.password = self._user_input('Rubrik password: '******'Invalid or missing authentication parameters.'
            self.logger.error('AuthenticationError # ' + msg)
            return False

        return True

    def load_interactive_auth(self, auth):
        """Get auth values from user."""
        self.auth = auth
        msg = 'Interactive authentication required.'
        self.logger.warning('AuthenticationWarning # ' + msg)
        # To Fix Clean
        self.auth.username = self._user_input('Rubrik username: '******'Rubrik password: '******'config']['useCredentialsFile']['value'] == 'True':
            self._update_auth_file()
        return self.auth

    def _update_auth_file(self):
        """Add server and username to auth file."""
        auth_dict = {
            'server': self.auth.server,
            'username': self.auth.username,
            'password': ''
        }
        file = self.conf_dict['config']['credentialsFile']['value']
        file = CONSTANTS.CONF_FOLDER + '/' + file
        self.create_json_file(auth_dict, file)

    def json_load(self, json_str):
        """Load json data."""
        self.called_tools.append('json_dump')

        # To Fix Clean
        try:
            json_dict = json.loads(json_str)
        except json.decoder.JSONDecodeError:
            json_dict = {}

        return json_dict

    def yaml_load(self, yaml_str):
        """Load yaml data."""
        self.called_tools.append('json_dump')
        return yaml.safe_load(yaml_str)

    def json_dump(self, json_dict):
        """Dump json data."""
        self.called_tools.append('json_dump')

        if not isinstance(json_dict, dict) and not isinstance(json_dict, list):
            json_dict = json.loads(json_dict)

        return json.dumps(json_dict, indent=2, sort_keys=True)

    def jsonfy(self, avar):
        """Load json data from string."""
        avar_dict = {}
        if isinstance(avar, requests.models.Response):
            avar_dict = self.json_load(avar.text)
        elif isinstance(avar, dict) or isinstance(avar, list):
            avar_dict = avar
        else:
            avar_dict['result'] = str(avar)

        return self.json_dump(avar_dict)

    def cp_dict(self, existing_dict):
        """Copy dictionary completely."""
        self.called_tools.append('cp_dict')
        return copy.deepcopy(existing_dict)

    def download_file(self, url):
        """Download file from provided url."""
        self.called_tools.append('download_file')
        pool = urllib3.PoolManager(cert_reqs='CERT_NONE')
        try:
            with pool.request('GET', url, preload_content=False) as file:
                content = file.read()
            if content == b'Route not defined.':
                error = str('Wrong or nonexistent URL [' + url + '], route is '
                            'not defined')
                msg = 'IOToolsError # ' + error
                self.logger.error(msg)
                raise RbkcliException.ToolsError(error)
            else:
                msg = str('IOTools # Successfully downloaded file [%s]' % url)
                self.logger.debug(msg)

        except urllib3.exceptions.MaxRetryError as error:
            msg = 'IOToolsError # ' + str(error)
            self.logger.error(msg)
            raise RbkcliException.ToolsError(str(error))

        return content

    def safe_create_folder(self, folder_path):
        """Create folders that don't exist in a path provided."""
        path = ''
        folder_path = folder_path.replace(CONSTANTS.BASE_FOLDER + "/", "")
        folders = folder_path.strip().split('/')
        try:
            for folder in folders:
                path = path + folder + '/'
                final_path = CONSTANTS.BASE_FOLDER + "/" + path

                if os.path.isdir(final_path):
                    msg = str('IOTools # Found existing folder [' +
                              final_path + '], not taking action.')
                    self.logger.debug(msg)
                else:
                    os.mkdir(final_path)
                    msg = str('IOTools # Could not find folder [' +
                              final_path + '], creating new.')
                    if self.logger.status == 'created':
                        self.logger.warning(msg)
                    else:
                        self.logger.debug(msg)

            return True
        except Exception as error:
            self.logger.error('IOToolsError # ' + str(error))
            return False

    def is_valid_uuid1(self, uuid_to_test, version=4):
        """Copy dictionary completely."""
        self.called_tools.append('is_valid_uuid')
        try:
            uuid_obj = UUID(uuid_to_test, version=version)
        except ValueError:
            return False

        return str(uuid_obj) == uuid_to_test

    def is_valid_uuid(self, uuid_to_test, version=4):
        """Copy dictionary completely."""
        # Because of the creation of the universal ID rbkcli no longer
        # verifies id validity
        del uuid_to_test, version
        self.called_tools.append('is_valid_uuid')
        return True

    @staticmethod
    def is_valid_ip(ip):
        """Validate if provided IP is valid, takes IPv4/IPv6."""
        try:
            # Python 2 compatibility
            try:
                ip = unicode(ip, "utf-8")
            except NameError:
                pass
            new_ip = ipaddress.ip_address(ip)
            del new_ip
            result = True
        except ValueError:
            result = False

        return result

    def is_valid_ip_port(self, ip_port):
        """Validate if provided IP is valid, takes IPv4/IPv6."""
        if ':' in ip_port:
            ip, port = ip_port.split(':')
            try:
                if (self.is_valid_ip(ip) and 65535 > int(port) > 0):
                    return True
                else:
                    return False
            except ValueError:
                return False
        else:
            return self.is_valid_ip(ip_port)

    def _resolve_target(self, target_name):
        """Resolve target fqdn to IP."""
        # Split port and fqdn
        if ':' in target_name:
            target_name = target_name.split(':')
            target_ip = target_name[0]
            port = ':' + target_name[1]
        else:
            port = ''
            target_ip = target_name
        try:
            target_ip = str(socket.gethostbyname(target_ip))
        except socket.gaierror:
            msg = 'Unable to resolve FQDN [%s].' % target_ip
            self.logger.error('ToolsError # ' + msg)
            raise RbkcliException.ToolsError(msg)

        return target_ip + port

    @staticmethod
    def is_not_empty_str(value):
        """Test if string is not empty."""
        return not value == ''

    @staticmethod
    def _user_input(msg, validator, inputer=input):
        """Validate user input."""
        value = inputer(msg)
        while not validator(value):
            value = input(msg)
        return value

    @staticmethod
    def gen_uuid():
        """Generate UUID version 4."""
        return uuid4()
Esempio n. 15
0
    def _iteration_context(self, definitions, json_data):
        """Define the context to use during iteration."""
        # Assign definitions to instance var.
        if definitions == []:
            definitions = {}
        self.definitions = definitions

        # Assign flag for returning the selected data.
        self.returning = True

        # Create the necessary var for map validated selection.
        self.cursor = ''
        self.level = 0
        # Create dictionary to save all maps and make it accessible.
        self.map = DotDict({})
        self.map.full = []

        # Dictionary with selected keys.
        self.selected = {}
        # TEST
        self.unselected = {}
        self.type_dict = {
            'str': 'str',
            'unicode': 'str',
            'bool': 'bool',
            'int': 'int',
            'dict': 'dict',
            'number': 'number',
            'list': 'list'
        }

        for key, value in definitions.items():
            self.selected[key] = 'N/A'
            self.unselected[key] = ''

        # Iterate provided json data.
        self._iterate_json(json_data)

        # Once the iteration is based on the metadata_key that is matched
        # then, the ones that are not matched are never treated, so:
        # Created the unselected dictionary that stores the keys that were
        # never analyzed.
        # If after the iteration, there are unselected fields that are
        # supposed to be filtered, then result should not be returned.
        # Practical meaning here is, if a filter/selection was ordered but the
        # field which we are filtering does not exist in the json at hand,
        # the code will interpret it as a miss match and not add it to the
        # list of results.
        for key in self.unselected:
            if (definitions[key]['filter_eq'] != ''
                    or definitions[key]['filter_aprox'] != ''
                    or definitions[key]['filter_not'] != ''
                    or definitions[key]['filter_not_aprox'] != ''):
                self.returning = False

        # From full map create simple keys map.
        self._gen_all_maps()

        # Use the flag to determine the return.
        if self.returning:
            return self.selected
        return {}