Пример #1
0
    def login(self, username, password):
        if username and password:
            cp_domain = self.get_option('domain')
            if cp_domain:
                payload = {
                    'user': username,
                    'password': password,
                    'domain': cp_domain
                }
            else:
                payload = {'user': username, 'password': password}
            url = '/web_api/login'
            response, response_data = self.send_request(url, payload)
        else:
            raise AnsibleConnectionFailure(
                'Username and password are required for login')

        try:
            self.connection._auth = {'X-chkp-sid': response_data['sid']}
            self.connection._session_uid = response_data['uid']
        except KeyError:
            raise ConnectionError(
                'Server returned response without token info during connection authentication: %s'
                % response)
Пример #2
0
    def run_commands(self, commands=None, check_rc=True):
        if commands is None:
            raise ValueError("'commands' value is required")
        responses = list()
        for cmd in to_list(commands):
            if not isinstance(cmd, collections.Mapping):
                cmd = {'command': cmd}

            output = cmd.pop('output', None)
            if output:
                raise ValueError(
                    "'output' value %s is not supported for run_commands" %
                    output)

            try:
                out = self.send_command(**cmd)
            except AnsibleConnectionFailure as e:
                if check_rc:
                    raise
                out = getattr(e, 'err', e)

            if out is not None:
                try:
                    out = to_text(out, errors='surrogate_or_strict').strip()
                except UnicodeError:
                    raise ConnectionError(
                        msg=u'Failed to decode output from %s: %s' %
                        (cmd, to_text(out)))

                try:
                    out = json.loads(out)
                except ValueError:
                    pass

                responses.append(out)
        return responses
Пример #3
0
    def run_commands(self, commands=None, check_rc=True):
        if commands is None:
            raise ValueError("'commands' value is required")

        responses = list()
        for cmd in to_list(commands):
            if not isinstance(cmd, Mapping):
                cmd = {"command": cmd}

            output = cmd.pop("output", None)
            if output:
                cmd["command"] = self._get_command_with_output(
                    cmd["command"], output)

            try:
                out = self.send_command(**cmd)
            except AnsibleConnectionFailure as e:
                if check_rc is True:
                    raise
                out = getattr(e, "err", e)

            if out is not None:
                try:
                    out = to_text(out, errors="surrogate_or_strict").strip()
                except UnicodeError:
                    raise ConnectionError(
                        message=u"Failed to decode output from %s: %s" %
                        (cmd, to_text(out)))

                try:
                    out = json.loads(out)
                except ValueError:
                    pass

                responses.append(out)
        return responses
Пример #4
0
    def login(self, username, password):
        def request_token_payload(username, password):
            return {
                'grant_type': 'password',
                'username': username,
                'password': password
            }

        def refresh_token_payload(refresh_token):
            return {
                'grant_type': 'refresh_token',
                'refresh_token': refresh_token
            }

        if self.refresh_token:
            payload = refresh_token_payload(self.refresh_token)
        elif username and password:
            payload = request_token_payload(username, password)
        else:
            raise AnsibleConnectionFailure(
                'Username and password are required for login in absence of refresh token'
            )

        dummy, response_data = self.connection.send(self._get_api_token_path(),
                                                    json.dumps(payload),
                                                    method=HTTPMethod.POST,
                                                    headers=BASE_HEADERS)
        response = self._response_to_json(response_data.getvalue())

        try:
            self.refresh_token = response['refresh_token']
            self.access_token = response['access_token']
        except KeyError:
            raise ConnectionError(
                'Server returned response without token info during connection authentication: %s'
                % response)
Пример #5
0
    def login(self, username, password):
        if username and password:
            cp_domain = self.get_option("domain")
            if cp_domain:
                payload = {
                    "user": username,
                    "password": password,
                    "domain": cp_domain,
                }
            else:
                payload = {"user": username, "password": password}
            url = "/web_api/login"
            response, response_data = self.send_request(url, payload)
        else:
            raise AnsibleConnectionFailure(
                "Username and password are required for login")

        try:
            self.connection._auth = {"X-chkp-sid": response_data["sid"]}
            self.connection._session_uid = response_data["uid"]
        except KeyError:
            raise ConnectionError(
                "Server returned response without token info during connection authentication: %s"
                % response)
Пример #6
0
    def run_commands(self, commands, check_rc=True):
        """Run list of commands on remote device and return results
        """
        responses = list()

        for item in to_list(commands):
            if item['output'] == 'json' and not item['command'].endswith(
                    '| json'):
                cmd = '%s | json' % item['command']
            elif item['output'] == 'text' and item['command'].endswith(
                    '| json'):
                cmd = item['command'].rsplit('|', 1)[0]
            else:
                cmd = item['command']

            try:
                out = self.get(cmd)
            except ConnectionError as e:
                if check_rc:
                    raise
                out = e

            try:
                out = to_text(out, errors='surrogate_or_strict').strip()
            except UnicodeError:
                raise ConnectionError(
                    msg=u'Failed to decode output from %s: %s' %
                    (cmd, to_text(out)))

            try:
                out = json.loads(out)
            except ValueError:
                pass

            responses.append(out)
        return responses
Пример #7
0
    def _run_queue(self, queue, output):
        if self._become:
            self.connection.queue_message(
                "warning",
                "become has no effect over httpapi. Use network_cli if privilege escalation is required",
            )

        request = request_builder(queue, output)
        headers = {"Content-Type": "application/json"}

        response, response_data = self.connection.send("/ins",
                                                       request,
                                                       headers=headers,
                                                       method="POST")

        try:
            response_data = json.loads(to_text(response_data.getvalue()))
        except ValueError:
            raise ConnectionError(
                "Response was not valid JSON, got {0}".format(
                    to_text(response_data.getvalue())))

        results = handle_response(response_data)
        return results
Пример #8
0
    def login(self, username, password):
        if username :
            if password == None:
                password = ''
            payload = {'username': str(username), 'password': str(password)}
            url = '/api/user/login'
            #response, response_data = self.send_request(url, payload)
            data = json.dumps(payload) if payload else '{}'

        else:
            raise AnsibleConnectionFailure('Username and password are required for login')

        try:
            #self._display_request()
            response, rep_payload  = self.connection.send(url, data, method='POST', headers=BASE_HEADERS)
            # logger.debug(str(url) + str(data) + str(response))

            value = self._get_response_value(rep_payload)
            response_data = self._response_to_json(value)
            cookie = response.info().get('Set-Cookie')
            self.connection._auth = {'Authorization':'Bearer ' +  response_data['token'], 'Cookie': cookie}
        except KeyError:
            raise ConnectionError(
                'Server returned response without token info during connection authentication: %s' % response)
Пример #9
0
    def file_upload(self, url, files, headers=None):
        """
        Workaround with requests library for lack of support in httpapi for
        multipart POST
        See:
        ansible/blob/devel/lib/ansible/plugins/connection/httpapi.py
        ansible/blob/devel/lib/ansible/module_utils/urls.py
        """

        if not HAS_REQUESTS_LIB:
            self._module.fail_json(msg=missing_required_lib(
                "requests"), exception=REQUESTS_IMP_ERR)

        if headers is None:
            headers = {}
        connection_details = self._connection.get_connection_details()
        if 'auth'in connection_details.keys():
            headers.update(connection_details['auth'])

        full_url = connection_details['url'] + url
        with open(files, 'rb') as file:
            file_param = {'fileupload': file}
            # Workaround for setting no_proxy based off acx_no_proxy flag
            if connection_details['no_proxy']:
                proxies = {'http': None, 'https': None}
                res = requests.post(
                    url=full_url, files=file_param, verify=False,
                    proxies=proxies, headers=headers)
            else:
                res = requests.post(
                    url=full_url, files=file_param, verify=False,
                    headers=headers)
        if res.status_code != 200:
            error_text = "Error while uploading firmware"
            raise ConnectionError(error_text, code=res.status_code)
        return res
Пример #10
0
    def login(self, username, password):
        payload = {}
        cp_domain = self.get_option('domain')
        cp_api_key = self.get_option('api_key')
        if cp_domain:
            payload['domain'] = cp_domain
        if username and password and not cp_api_key:
            payload['user'] = username
            payload['password'] = password
        elif cp_api_key and not username and not password:
            payload['api-key'] = cp_api_key
        else:
            raise AnsibleConnectionFailure(
                '[Username and password] or api_key are required for login')
        url = '/web_api/login'
        response, response_data = self.send_request(url, payload)

        try:
            self.connection._auth = {'X-chkp-sid': response_data['sid']}
            self.connection._session_uid = response_data['uid']
        except KeyError:
            raise ConnectionError(
                'Server returned response without token info during connection authentication: %s'
                % response)
Пример #11
0
 def _response_to_json(self, response_text):
     try:
         return json.loads(response_text) if response_text else {}
     # JSONDecodeError only available on Python 3.5+
     except ValueError:
         raise ConnectionError('Invalid JSON response: %s' % response_text)
Пример #12
0
 def _response_to_json(response_text):
     try:
         return json.loads(response_text) if response_text else {}
     # JSONDecodeError only available on Python 3.5+
     except getattr(json.decoder, 'JSONDecodeError', ValueError):
         raise ConnectionError('Invalid JSON response: %s' % response_text)
Пример #13
0
    def file_upload(self, url, files, headers=None):
        """
        Workaround with requests library for lack of support in httpapi for
        multipart POST
        See:
        ansible/blob/devel/lib/ansible/plugins/connection/httpapi.py
        ansible/blob/devel/lib/ansible/module_utils/urls.py
        """

        if not HAS_REQUESTS_LIB:
            self._module.fail_json(msg=missing_required_lib("requests"),
                                   exception=REQUESTS_IMP_ERR)

        if headers is None:
            headers = {}
        connection_details = self._connection.get_connection_details()

        full_url = connection_details['url'] + url
        with open(files, 'rb') as file:
            file_param = {'fileupload': file}

            # Get Credentials
            user = connection_details['remote_user']
            password = connection_details['password']

            # Workaround for setting no_proxy based off acx_no_proxy flag
            if connection_details['no_proxy']:
                proxies = {'http': None, 'https': None}
                # Using proxies
                # Perform Login
                response_login = requests.post(
                    connection_details['url'] + \
                    "/rest/v1/login?username={}&password={}".format(
                        user, password
                    ),
                    verify=False, timeout=5, proxies=proxies)
                # Perform File Upload
                res = requests.post(url=full_url,
                                    files=file_param,
                                    verify=False,
                                    proxies=proxies,
                                    cookies=response_login.cookies)
                # Perform Logout
                response_logout = requests.post(connection_details['url'] +
                                                "/rest/v1/logout",
                                                verify=False,
                                                proxies=proxies,
                                                cookies=response_login.cookies)

            else:
                # No proxies
                # Perform Login
                response_login = requests.post(
                    connection_details['url'] + \
                    "/rest/v1/login?username={}&password={}".format(
                        user, password
                    ),
                    verify=False, timeout=5)
                # Perform File Upload
                res = requests.post(url=full_url,
                                    files=file_param,
                                    verify=False,
                                    cookies=response_login.cookies)
                # Perform Logout
                response_logout = requests.post(connection_details['url'] +
                                                "/rest/v1/logout",
                                                verify=False,
                                                cookies=response_login.cookies)

        if res.status_code != 200:
            error_text = "Error while uploading firmware"
            raise ConnectionError(error_text, code=res.status_code)
        return res
Пример #14
0
    def edit_config(
        self,
        candidate=None,
        commit=True,
        admin=False,
        exclusive=False,
        replace=None,
        comment=None,
        label=None,
    ):
        operations = self.get_device_operations()
        self.check_edit_config_capability(
            operations,
            candidate,
            commit,
            replace,
            comment,
        )

        resp = {}
        results = []
        requests = []

        self.configure(admin=admin, exclusive=exclusive)

        if replace:
            candidate = "load {0}".format(replace)

        for line in to_list(candidate):
            if not isinstance(line, Mapping):
                line = {"command": line}
            cmd = line["command"]
            results.append(self.send_command(**line))
            requests.append(cmd)

        # Before any commit happened, we can get a real configuration
        # diff from the device and make it available by the iosxr_config module.
        # This information can be useful either in check mode or normal mode.
        resp["show_commit_config_diff"] = self.get("show commit changes diff")

        if commit:
            try:
                self.commit(comment=comment, label=label, replace=replace)
            except AnsibleConnectionFailure as exc:
                error_msg = to_text(exc, errors="surrogate_or_strict").strip()
                if "Invalid input detected" in error_msg and "comment" in error_msg:
                    msg = (
                        "value of comment option '%s' is ignored as it in not supported by IOSXR"
                        % comment
                    )
                    self._connection.queue_message("warning", msg)
                    comment = None
                    self.commit(comment=comment, label=label, replace=replace)
                else:
                    raise ConnectionError(error_msg)

        else:
            self.discard_changes()

        if not self.get_option("commit_confirmed"):
            self.abort(admin=admin)

        resp["request"] = requests
        resp["response"] = results
        return resp
Пример #15
0
    def send_request(self, method, path, data=None):
        ''' This method handles all MSO REST API requests other than login '''

        self.error = None
        self.path = ''
        self.status = -1
        self.info = {}
        self.method = 'GET'

        if data is None:
            data = {}

        self.connection.queue_message('vvvv', 'send_request method called')
        # # Case1: List of hosts is provided
        # self.backup_hosts = self.set_backup_hosts()
        # if not self.backup_hosts:
        if self.connection._connected is True and self.params.get(
                'host') != self.connection.get_option('host'):
            self.connection._connected = False
            self.connection.queue_message(
                'vvvv',
                'send_request reseting connection as host has changed from {0} to {1}'
                .format(self.connection.get_option('host'),
                        self.params.get('host')))

        if self.params.get('host') is not None:
            self.connection.set_option('host', self.params.get('host'))

        else:
            try:
                with open('my_hosts.pk', 'rb') as fi:
                    self.host_counter = pickle.load(fi)
            except FileNotFoundError:
                pass
            try:
                self.connection.set_option(
                    "host", self.backup_hosts[self.host_counter])
            except IndexError:
                pass

        if self.params.get('port') is not None:
            self.connection.set_option("port", self.params.get('port'))

        if self.params.get('username') is not None:
            self.connection.set_option("remote_user",
                                       self.params.get('username'))

        if self.params.get('password') is not None:
            self.connection.set_option("password", self.params.get('password'))

        if self.params.get('use_proxy') is not None:
            self.connection.set_option("use_proxy",
                                       self.params.get('use_proxy'))

        if self.params.get('use_ssl') is not None:
            self.connection.set_option("use_ssl", self.params.get('use_ssl'))

        if self.params.get('validate_certs') is not None:
            self.connection.set_option("validate_certs",
                                       self.params.get('validate_certs'))

        # Perform some very basic path input validation.
        path = str(path)
        if path[0] != '/':
            self.error = dict(
                code=self.status,
                message=
                'Value of <path> does not appear to be formated properly')
            raise ConnectionError(
                json.dumps(self._verify_response(None, method, path, None)))
        full_path = self.connection.get_option('host') + path
        try:
            self.connection.queue_message(
                'vvvv',
                'send_request() - connection.send({0}, {1}, {2}, {3})'.format(
                    path, data, method, self.headers))
            response, rdata = self.connection.send(path,
                                                   data,
                                                   method=method,
                                                   headers=self.headers)
        except ConnectionError:
            self.connection.queue_message(
                'vvvv', 'login() - ConnectionError Exception')
            raise
        except Exception as e:
            self.connection.queue_message(
                'vvvv', 'send_request() - Generic Exception')
            if self.error is None:
                self.error = dict(
                    code=self.status,
                    message='MSO HTTPAPI send_request() Exception: {0} - {1}'.
                    format(e, traceback.format_exc()))
            raise ConnectionError(
                json.dumps(self._verify_response(None, method, full_path,
                                                 None)))
        return self._verify_response(response, method, full_path, rdata)
Пример #16
0
 def test_get_known_token_paths_with_failed_api_call(self, get_list_of_supported_api_versions_mock):
     get_list_of_supported_api_versions_mock.side_effect = ConnectionError('test errro message')
     result = self.ftd_plugin._get_known_token_paths()
     assert result == [TOKEN_PATH_TEMPLATE.format(version) for version in DEFAULT_API_VERSIONS]
Пример #17
0
def main(args=None):
    """ Called to initiate the connect to the remote device
    """

    parser = opt_help.create_base_parser(prog='ansible-connection')
    opt_help.add_verbosity_options(parser)
    parser.add_argument('playbook_pid')
    parser.add_argument('task_uuid')
    args = parser.parse_args(args[1:] if args is not None else args)

    # initialize verbosity
    display.verbosity = args.verbosity

    rc = 0
    result = {}
    messages = list()
    socket_path = None

    # Need stdin as a byte stream
    stdin = sys.stdin.buffer

    # Note: update the below log capture code after Display.display() is refactored.
    saved_stdout = sys.stdout
    sys.stdout = io.StringIO()

    try:
        # read the play context data via stdin, which means depickling it
        opts_data = read_stream(stdin)
        init_data = read_stream(stdin)

        pc_data = pickle.loads(init_data, encoding='bytes')
        options = pickle.loads(opts_data, encoding='bytes')

        play_context = PlayContext()
        play_context.deserialize(pc_data)

    except Exception as e:
        rc = 1
        result.update({
            'error': to_text(e),
            'exception': traceback.format_exc()
        })

    if rc == 0:
        ssh = connection_loader.get('ssh', class_only=True)
        ansible_playbook_pid = args.playbook_pid
        task_uuid = args.task_uuid
        cp = ssh._create_control_path(play_context.remote_addr,
                                      play_context.port,
                                      play_context.remote_user,
                                      play_context.connection,
                                      ansible_playbook_pid)
        # create the persistent connection dir if need be and create the paths
        # which we will be using later
        tmp_path = unfrackpath(C.PERSISTENT_CONTROL_PATH_DIR)
        makedirs_safe(tmp_path)

        socket_path = unfrackpath(cp % dict(directory=tmp_path))
        lock_path = unfrackpath("%s/.ansible_pc_lock_%s" %
                                os.path.split(socket_path))

        with file_lock(lock_path):
            if not os.path.exists(socket_path):
                messages.append(
                    ('vvvv',
                     'local domain socket does not exist, starting it'))
                original_path = os.getcwd()
                r, w = os.pipe()
                pid = fork_process()

                if pid == 0:
                    try:
                        os.close(r)
                        wfd = os.fdopen(w, 'w')
                        process = ConnectionProcess(wfd, play_context,
                                                    socket_path, original_path,
                                                    task_uuid,
                                                    ansible_playbook_pid)
                        process.start(options)
                    except Exception:
                        messages.append(('error', traceback.format_exc()))
                        rc = 1

                    if rc == 0:
                        process.run()
                    else:
                        process.shutdown()

                    sys.exit(rc)

                else:
                    os.close(w)
                    rfd = os.fdopen(r, 'r')
                    data = json.loads(rfd.read(), cls=AnsibleJSONDecoder)
                    messages.extend(data.pop('messages'))
                    result.update(data)

            else:
                messages.append(
                    ('vvvv', 'found existing local domain socket, using it!'))
                conn = Connection(socket_path)
                try:
                    conn.set_options(direct=options)
                except ConnectionError as exc:
                    messages.append(('debug', to_text(exc)))
                    raise ConnectionError(
                        'Unable to decode JSON from response set_options. See the debug log for more information.'
                    )
                pc_data = to_text(init_data)
                try:
                    conn.update_play_context(pc_data)
                    conn.set_check_prompt(task_uuid)
                except Exception as exc:
                    # Only network_cli has update_play context and set_check_prompt, so missing this is
                    # not fatal e.g. netconf
                    if isinstance(exc, ConnectionError) and getattr(
                            exc, 'code', None) == -32601:
                        pass
                    else:
                        result.update({
                            'error': to_text(exc),
                            'exception': traceback.format_exc()
                        })

    if os.path.exists(socket_path):
        messages.extend(Connection(socket_path).pop_messages())
    messages.append(('vvvv', sys.stdout.getvalue()))
    result.update({'messages': messages, 'socket_path': socket_path})

    sys.stdout = saved_stdout
    if 'exception' in result:
        rc = 1
        sys.stderr.write(json.dumps(result, cls=AnsibleJSONEncoder))
    else:
        rc = 0
        sys.stdout.write(json.dumps(result, cls=AnsibleJSONEncoder))

    sys.exit(rc)
Пример #18
0
    def login(self, username, password):
        ''' Log in to MSO '''
        # Perform login request
        self.connection.queue_message(
            'vvvv',
            'Starting Login to {0}'.format(self.connection.get_option('host')))

        method = 'POST'
        path = '/mso/api/v1/auth/login'
        full_path = self.connection.get_option('host') + path

        if (self.params.get('login_domain')
                is not None) and (self.params.get('login_domain') != 'Local'):
            domain_id = self._get_login_domain_id(
                self.params.get('login_domain'))
            payload = {
                'username': self.params.get('username'),
                'password': self.params.get('password'),
                'domainId': domain_id
            }
        else:
            payload = {
                'username': self.params.get('username'),
                'password': self.params.get('password')
            }
        data = json.dumps(payload)
        try:
            self.connection.queue_message(
                'vvvv', 'login() - connection.send({0}, {1}, {2}, {3})'.format(
                    path, data, method, self.headers))
            response, response_data = self.connection.send(
                path, data, method=method, headers=self.headers)
            # Handle MSO response
            self.status = response.getcode()
            if self.status != 201:
                self.connection.queue_message(
                    'vvvv',
                    'login status incorrect status={0}'.format(self.status))
                json_response = self._response_to_json(response_data)
                self.error = dict(
                    code=self.status,
                    message='Authentication failed: {0}'.format(json_response))
                raise ConnectionError(
                    json.dumps(
                        self._verify_response(response, method, full_path,
                                              response_data)))
            self.connection._auth = {
                'Authorization':
                'Bearer {0}'.format(
                    self._response_to_json(response_data).get('token'))
            }

        except ConnectionError:
            self.connection.queue_message(
                'vvvv', 'login() - ConnectionError Exception')
            raise
        except Exception as e:
            self.connection.queue_message('vvvv',
                                          'login() - Generic Exception')
            self.error = dict(
                code=self.status,
                message='Authentication failed: Request failed: {0}'.format(e))
            raise ConnectionError(
                json.dumps(self._verify_response(None, method, full_path,
                                                 None)))
Пример #19
0
    def login(self, username, password):
        ''' Log in to ND '''
        # Perform login request
        self.connection.queue_message(
            'vvvv',
            'Starting Login to {0}'.format(self.connection.get_option('host')))

        method = 'POST'
        path = '/login'
        full_path = self.connection.get_option('host') + path
        # TODO: Fix when username and password are not used in ND module
        login_domain = 'DefaultAuth'
        if self.params.get('login_domain') != 'local':
            login_domain = self.params.get('login_domain')

        payload = {
            'username': self.params.get('username'),
            'password': self.params.get('password'),
            'domain': login_domain
        }
        data = json.dumps(payload)
        try:
            self.connection.queue_message(
                'vvvv', 'login() - connection.send({0}, {1}, {2}, {3})'.format(
                    path, data, method, self.headers))
            response, response_data = self.connection.send(
                path, data, method=method, headers=self.headers)

            # Handle ND response
            self.status = response.getcode()
            if self.status not in [200, 201]:
                self.connection.queue_message(
                    'vvvv',
                    'login status incorrect status={0}'.format(self.status))
                json_response = self._response_to_json(response_data)
                self.error = dict(
                    code=self.status,
                    message='Authentication failed: {0}'.format(json_response))
                raise ConnectionError(
                    json.dumps(
                        self._verify_response(response, method, full_path,
                                              response_data)))
            self.connection._auth = {
                'Authorization':
                'Bearer {0}'.format(
                    self._response_to_json(response_data).get('token'))
            }

        except ConnectionError:
            self.connection.queue_message(
                'vvvv', 'login() - ConnectionError Exception')
            raise
        except Exception as e:
            self.connection.queue_message('vvvv',
                                          'login() - Generic Exception')
            self.error = dict(
                code=self.status,
                message='Authentication failed: Request failed: {0}'.format(e))
            raise ConnectionError(
                json.dumps(self._verify_response(None, method, full_path,
                                                 None)))