def get_locked_adom_list(self):
        """
        Gets the list of locked adoms
        """
        try:
            locked_list = list()
            locked_by_user_list = dict()
            for adom in self._adom_list:
                adom_lock_info = self.get_lock_info(adom=adom)
                self.log('lockinfo for adom:%s' % (adom))
                self.log(json.dumps(adom_lock_info, indent=4))
                if adom_lock_info[1]['status']['code'] != 0:
                    continue
                # if 'data' is not in the response, the adom is locked by no one
                if 'data' not in adom_lock_info[1]:
                    continue
                locked_list.append(to_text(adom))
                locked_by_user_list[to_text(adom)] = to_text(adom_lock_info[1]['data'][0]['lock_user'])

            self._locked_adom_list = locked_list
            self._locked_adoms_by_user = locked_by_user_list
            self.log('locked adom list: %s' % (self._locked_adom_list))
            self.log('locked adom and user list: %s' % (self._locked_adoms_by_user))

        except Exception as err:
            raise FMGBaseException(msg=("An error occurred while trying to get the locked adom list. Error: "
                                        + to_text(err)))
Ejemplo n.º 2
0
    def send_request(self,
                     request_method,
                     path,
                     payload=None,
                     headers=None,
                     **kwargs):
        headers = headers if headers else BASE_HEADERS

        try:
            self._display_request(request_method)
            response, response_data = self.connection.send(
                path,
                payload,
                method=request_method,
                headers=headers,
                **kwargs)
            value = self._get_response_value(response_data)
            return response.getcode(), self._response_to_json(value)
        except AnsibleConnectionFailure as e:
            if to_text('401') in to_text(e):
                return 401, 'Authentication failure'
            else:
                return 404, 'Object not found'
        except HTTPError as e:
            error = json.loads(e.read())
            return e.code, error
Ejemplo n.º 3
0
    def send_request(self, request_method, path, payload=None):
        # payload = json.dumps(payload) if payload else '{}'

        try:
            self._display_request(request_method, path)
            response, response_data = self.connection.send(
                path,
                payload,
                method=request_method,
                headers=BASE_HEADERS,
                force_basic_auth=True,
            )
            value = self._get_response_value(response_data)

            return response.getcode(), self._response_to_json(value)
        except AnsibleConnectionFailure as e:
            self.connection.queue_message("vvv",
                                          "AnsibleConnectionFailure: %s" % e)
            if to_text("Could not connect to") in to_text(e):
                raise
            if to_text("401") in to_text(e):
                return 401, "Authentication failure"
            else:
                return 404, "Object not found"
        except HTTPError as e:
            error = json.loads(e.read())
            return e.code, error
Ejemplo n.º 4
0
    def send_request(self,
                     request_method="POST",
                     path="/api_jsonrpc.php",
                     payload=None):
        if not payload:
            payload = {}

        try:
            self._display_request(request_method, path)
            response, response_data = self.connection.send(
                path, payload, method=request_method, headers=BASE_HEADERS)
            value = to_text(response_data.getvalue())

            try:
                json_data = json.loads(value) if value else {}
                if "result" in json_data:
                    json_data = json_data["result"]
            # JSONDecodeError only available on Python 3.5+
            except ValueError:
                raise ConnectionError("Invalid JSON response: %s" % value)

            return response.getcode(), json_data
        except AnsibleConnectionFailure as e:
            self.connection.queue_message("vvv",
                                          "AnsibleConnectionFailure: %s" % e)
            if to_text("Could not connect to") in to_text(e):
                raise
            if to_text("401") in to_text(e):
                return 401, "Authentication failure"
            else:
                return 404, "Object not found"
        except Exception as e:
            raise e
Ejemplo n.º 5
0
    def login(self, username, password):
        login_path = "/rest/authentication/login/primary"
        data = {
            "dsCredentials": {
                "password": to_text(password),
                "userName": to_text(username),
            }
        }

        code, auth_token = self.send_request("POST", login_path, data=data)
        try:
            # This is still sent as an HTTP header, so we can set our connection's _auth
            # variable manually. If the token is returned to the device in another way,
            # you will have to keep track of it another way and make sure that it is sent
            # with the rest of the request from send_request()
            self.connection._auth = {"Cookie": "sID={0}".format(auth_token)}

            # Have to carry this around because variuous Trend Micro Deepsecurity REST
            # API endpoints want the sID as a querystring parameter instead of honoring
            # the session Cookie
            self._auth_token = auth_token
        except KeyError:
            raise AnsibleAuthenticationFailure(
                message="Failed to acquire login token."
            )
Ejemplo n.º 6
0
    def get_locked_adom_list(self):
        """
        Gets the list of locked adoms
        """
        try:
            locked_list = list()
            locked_by_user_list = list()
            for adom in self._adom_list:
                adom_lock_info = self.get_lock_info(adom=adom)
                try:
                    if adom_lock_info[1]["status"]["message"] == "OK":
                        continue
                except IndexError as err:
                    pass
                try:
                    if adom_lock_info[1][0]["lock_user"]:
                        locked_list.append(to_text(adom))
                    if adom_lock_info[1][0][
                            "lock_user"] == self._logged_in_user:
                        locked_by_user_list.append({
                            "adom":
                            to_text(adom),
                            "user":
                            to_text(adom_lock_info[1][0]["lock_user"])
                        })
                except Exception as err:
                    raise FMGBaseException(err)
            self._locked_adom_list = locked_list
            self._locked_adoms_by_user = locked_by_user_list

        except Exception as err:
            raise FMGBaseException(msg=(
                "An error occurred while trying to get the locked adom list. Error: "
                + to_text(err)))
Ejemplo n.º 7
0
    def send_request(self, method, params):
        """
        Responsible for actual sending of data to the connection httpapi base plugin. Does some formatting too.
        :param params: A formatted dictionary that was returned by self.common_datagram_params()
        before being called here.
        :param method: The preferred API Request method (GET, ADD, POST, etc....)
        :type method: basestring

        :return: Dictionary of status, if it logged in or not.
        """
        try:
            if self.sid is None and params[0]["url"] != "sys/login/user":
                try:
                    self.connection._connect()
                except Exception as err:
                    raise FMGBaseException(
                        msg=
                        "An problem happened with the httpapi plugin self-init connection process. "
                        "Error: " + to_text(err))
        except IndexError:
            raise FMGBaseException(
                "An attempt was made at communicating with a FMG with "
                "no valid session and an incorrectly formatted request.")
        except Exception as err:
            raise FMGBaseException(
                "An attempt was made at communicating with a FMG with "
                "no valid session and an unexpected error was discovered. \n Error: "
                + to_text(err))

        self._update_request_id()
        json_request = {
            "method": method,
            "params": params,
            "session": self.sid,
            "id": self.req_id,
            "verbose": 1
        }
        data = json.dumps(json_request,
                          ensure_ascii=False).replace('\\\\', '\\')
        try:
            # Sending URL and Data in Unicode, per Ansible Specifications for Connection Plugins
            response, response_data = self.connection.send(
                path=to_text(self._url),
                data=to_text(data),
                headers=BASE_HEADERS)
            # Get Unicode Response - Must convert from StringIO to unicode first so we can do a replace function below
            result = json.loads(to_text(response_data.getvalue()))
            self._update_self_from_response(result, self._url, data)
            return self._handle_response(result)
        except Exception as err:
            raise FMGBaseException(err)
Ejemplo n.º 8
0
    def _validate_response(http_code, http_response):

        # XML API piggybacks on HTTP 400 and 403 error codes.
        if http_code not in [200, 400, 403]:
            raise ConnectionError("Invalid response from API")

        data = to_text(http_response)
        root = ET.fromstring(data)

        display.vvvv("_validate_response(): response = {0}".format(data))

        status = root.attrib.get("status")
        api_code = root.attrib.get("code")
        msg = root.findtext(".//msg/line")

        # Successful responses that AREN'T keygen type all have 'success'
        # attributes.
        if status != "success":
            message = ""

            if api_code and api_code in PANOS_API_CODES:
                message = "{0} ({1}): {2}".format(api_code,
                                                  PANOS_API_CODES[api_code],
                                                  msg)
            else:
                message = "{0}".format(msg)

            raise ConnectionError(message)

        # For whatever reason, Ansible wants a JSON serializable response ONLY,
        # so return unparsed data.
        return data
Ejemplo n.º 9
0
    def send_request(self, **message_kwargs):
        """
        Responsible for actual sending of data to the connection httpapi base plugin.
        :param message_kwargs: A formatted dictionary containing request info: url, data, method

        :return: Status code and response data.
        """
        url = message_kwargs.get('url', '/')
        data = message_kwargs.get('data', '')
        method = message_kwargs.get('method', 'GET')

        if self._ccsrftoken == '' and not (method == 'POST'
                                           and 'logincheck' in url):
            raise Exception('Not logged in. Please login first')

        headers = {}
        if self._ccsrftoken != '':
            headers['x-csrftoken'] = self._ccsrftoken

        if method == 'POST' or 'PUT':
            headers['Content-Type'] = 'application/json'

        try:
            response, response_data = self._connection.send(url,
                                                            data,
                                                            headers=headers,
                                                            method=method)

            return response.status, to_text(response_data.getvalue())
        except Exception as err:
            raise Exception(err)
Ejemplo n.º 10
0
    def send_request(self,
                     url_path,
                     http_method,
                     body_params=None,
                     path_params=None,
                     query_params=None):
        url = construct_url_path(url_path, path_params, query_params)
        data = json.dumps(body_params) if body_params else None
        try:
            self._display(http_method, 'url', url)
            if data:
                self._display(http_method, 'data', data)

            response, response_data = self.connection.send(
                url, data, method=http_method, headers=BASE_HEADERS)

            value = self._get_response_value(response_data)
            self._display(http_method, 'response', value)

            return {
                ResponseParams.SUCCESS: True,
                ResponseParams.STATUS_CODE: response.getcode(),
                ResponseParams.RESPONSE: self._response_to_json(value)
            }
        # Being invoked via JSON-RPC, this method does not serialize and pass HTTPError correctly to the method caller.
        # Thus, in order to handle non-200 responses, we need to wrap them into a simple structure and pass explicitly.
        except HTTPError as e:
            error_msg = to_text(e.read())
            self._display(http_method, 'error', error_msg)
            return {
                ResponseParams.SUCCESS: False,
                ResponseParams.STATUS_CODE: e.code,
                ResponseParams.RESPONSE: self._response_to_json(error_msg)
            }
Ejemplo n.º 11
0
    def get_devices(self,
                    name=None,
                    osversion=None,
                    devicefamily=None,
                    serialnumber=None,
                    platform=None,
                    managedstatus=None,
                    connectionstatus=None,
                    attribute_column_0=None,
                    ip_address=None):
        '''
        Querries Space API and returns list of any devices matching filter(s) or None
        '''
        query_strs = []
        self.space_request.headers = {
            "Accept":
            "application/vnd.net.juniper.space.device-management.devices+json;version=2"
        }
        if name:
            query_strs.append(quote("name eq '{0}'".format(to_text(name))))

        if osversion:
            query_strs.append(quote("OSversion eq '{0}'".format(osversion)))

        if devicefamily:
            query_strs.append(
                quote("deviceFamily eq '{0}'".format(devicefamily)))

        if serialnumber:
            query_strs.append(
                quote("SerialNumber eq '{0}'".format(serialnumber)))

        if platform:
            query_strs.append(quote("platform eq '{0}'".format(platform)))

        if managedstatus:
            query_strs.append(
                quote("managedStatus eq '{0}'".format(managedstatus)))

        if connectionstatus:
            query_strs.append(
                quote("connectionStatus eq '{0}'".format(connectionstatus)))

        if attribute_column_0:
            query_strs.append(
                quote(
                    "attribute-column-0 eq '{0}'".format(attribute_column_0)))

        if ip_address:
            query_strs.append(quote("ipAddr eq '{0}'".format(ip_address)))

        if query_strs:
            code, response = self.space_request.get_by_path(
                "/api/space/device-management/devices?filter=({0})".format(
                    "%20and%20".join(query_strs)))
            return self._return_list(response['devices'])
        else:
            code, response = self.space_request.get_by_path(
                "/api/space/device-management/devices")
            return self._return_list(response['devices'])
Ejemplo n.º 12
0
    def send_request(self, **message_kwargs):
        """
        Responsible for actual sending of data to the connection httpapi base plugin.
        :param message_kwargs: A formatted dictionary containing request info: url, data, method

        :return: Status code and response data.
        """

        url = message_kwargs.get('url', '/')
        if self.get_access_token() is not None:
            url = self._concat_token(message_kwargs.get('url', '/'))
        data = message_kwargs.get('data', '')
        method = message_kwargs.get('method', 'GET')
        params = message_kwargs.get('params', {})

        url = self._concat_params(url, params)
        self.log('send request: METHOD:%s URL:%s DATA:%s' % (method, url, data))
        try:
            response, response_data = self.connection.send(url, data, method=method)

            json_formatted = to_text(response_data.getvalue())

            return response.status, json_formatted
        except Exception as err:
            raise Exception(err)
Ejemplo n.º 13
0
    def _validate_response(http_code, http_response):

        # Valid XML-API responses can be contained in the following HTTP status
        # codes:
        #   400 - Bad Request (malformed request)
        #   403 - Forbidden (invalid credentials)
        #   200 - OK (HTTP request was OK, but still can be an XML-API error)
        if http_code not in [200, 400, 403]:
            raise ConnectionError("Invalid response from API")

        data = to_text(http_response)
        root = ET.fromstring(data)

        display.vvvv("_validate_response(): response = {0}".format(data))

        status = root.attrib.get("status")
        api_code = root.attrib.get("code")

        if status == "error":
            msg = None

            # Error messages can be in multiple locations in the response.
            if root.findtext("./result/msg"):
                msg = root.findtext("./result/msg")

            elif len(root.findall("./msg/line")) > 0:
                lines = root.findall("./msg/line")
                msg = ", ".join([line.text for line in lines])

            raise PanOSAPIError(api_code, msg)

        # For whatever reason, Ansible wants a JSON serializable response ONLY,
        # so return unparsed data.
        return data
Ejemplo n.º 14
0
 def _response_to_json(response_data):
     response_text = to_text(response_data)
     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)
Ejemplo n.º 15
0
def get_s3_connection(module, aws_connect_kwargs, location, rgw, s3_url, sig_4=False):
    if s3_url and rgw:  # TODO - test this
        rgw = urlparse(s3_url)
        params = dict(module=module, conn_type='client', resource='s3', use_ssl=rgw.scheme == 'https', region=location, endpoint=s3_url, **aws_connect_kwargs)
    elif is_fakes3(s3_url):
        fakes3 = urlparse(s3_url)
        port = fakes3.port
        if fakes3.scheme == 'fakes3s':
            protocol = "https"
            if port is None:
                port = 443
        else:
            protocol = "http"
            if port is None:
                port = 80
        params = dict(module=module, conn_type='client', resource='s3', region=location,
                      endpoint="%s://%s:%s" % (protocol, fakes3.hostname, to_text(port)),
                      use_ssl=fakes3.scheme == 'fakes3s', **aws_connect_kwargs)
    else:
        params = dict(module=module, conn_type='client', resource='s3', region=location, endpoint=s3_url, **aws_connect_kwargs)
        if module.params['mode'] == 'put' and module.params['encryption_mode'] == 'aws:kms':
            params['config'] = botocore.client.Config(signature_version='s3v4')
        elif module.params['mode'] in ('get', 'getstr') and sig_4:
            params['config'] = botocore.client.Config(signature_version='s3v4')
        if module.params['dualstack']:
            dualconf = botocore.client.Config(s3={'use_dualstack_endpoint': True})
            if 'config' in params:
                params['config'] = params['config'].merge(dualconf)
            else:
                params['config'] = dualconf
    return boto3_conn(**params)
Ejemplo n.º 16
0
def destroy_bucket(s3_client, module):

    force = module.params.get("force")
    name = module.params.get("name")
    try:
        bucket_is_present = bucket_exists(s3_client, name)
    except EndpointConnectionError as e:
        module.fail_json_aws(e, msg="Invalid endpoint provided: %s" % to_text(e))
    except (BotoCoreError, ClientError) as e:
        module.fail_json_aws(e, msg="Failed to check bucket presence")

    if not bucket_is_present:
        module.exit_json(changed=False)

    if force:
        # if there are contents then we need to delete them before we can delete the bucket
        try:
            for keys in paginated_list(s3_client, Bucket=name):
                formatted_keys = [{'Key': key} for key in keys]
                if formatted_keys:
                    s3_client.delete_objects(Bucket=name, Delete={'Objects': formatted_keys})
        except (BotoCoreError, ClientError) as e:
            module.fail_json_aws(e, msg="Failed while deleting bucket")

    try:
        delete_bucket(s3_client, name)
        s3_client.get_waiter('bucket_not_exists').wait(Bucket=name)
    except WaiterError as e:
        module.fail_json_aws(e, msg='An error occurred waiting for the bucket to be deleted.')
    except (BotoCoreError, ClientError) as e:
        module.fail_json_aws(e, msg="Failed to delete bucket")

    module.exit_json(changed=True)
Ejemplo n.º 17
0
 def get_lock_info(self, adom=None):
     """
     Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible
     for some reason, then unlock it.
     """
     if not adom or adom == "root":
         url = "/dvmdb/adom/root/workspace/lockinfo"
     else:
         if adom.lower() == "global":
             url = "/dvmdb/global/workspace/lockinfo/"
         else:
             url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(
                 adom=adom)
     datagram = {}
     data = self._tools.format_request(FMGRMethods.GET, url, **datagram)
     resp_obj = self.send_request(FMGRMethods.GET, data)
     code = resp_obj[0]
     if code != 0:
         self._module.fail_json(
             msg=("An error occurred trying to get the ADOM Lock Info. "
                  "Error: " + to_text(resp_obj)))
     elif code == 0:
         try:
             if resp_obj[1]["status"]["message"] == "OK":
                 self._lock_info = None
         except Exception:
             self._lock_info = resp_obj[1]
     return resp_obj
Ejemplo n.º 18
0
def destroy_bucket(s3_client, module):

    force = module.params.get("force")
    name = module.params.get("name")
    try:
        bucket_is_present = bucket_exists(s3_client, name)
    except EndpointConnectionError as e:
        module.fail_json_aws(e,
                             msg="Invalid endpoint provided: %s" % to_text(e))
    except (BotoCoreError, ClientError) as e:
        module.fail_json_aws(e, msg="Failed to check bucket presence")

    if not bucket_is_present:
        module.exit_json(changed=False)

    if force:
        # if there are contents then we need to delete them (including versions) before we can delete the bucket
        try:
            for key_version_pairs in paginated_versions_list(s3_client,
                                                             Bucket=name):
                formatted_keys = [{
                    'Key': key,
                    'VersionId': version
                } for key, version in key_version_pairs]
                for fk in formatted_keys:
                    # remove VersionId from cases where they are `None` so that
                    # unversioned objects are deleted using `DeleteObject`
                    # rather than `DeleteObjectVersion`, improving backwards
                    # compatibility with older IAM policies.
                    if not fk.get('VersionId'):
                        fk.pop('VersionId')

                if formatted_keys:
                    resp = s3_client.delete_objects(
                        Bucket=name, Delete={'Objects': formatted_keys})
                    if resp.get('Errors'):
                        module.fail_json(
                            msg=
                            'Could not empty bucket before deleting. Could not delete objects: {0}'
                            .format(', '.join(
                                [k['Key'] for k in resp['Errors']])),
                            errors=resp['Errors'],
                            response=resp)
        except (BotoCoreError, ClientError) as e:
            module.fail_json_aws(e, msg="Failed while deleting bucket")

    try:
        delete_bucket(s3_client, name)
        s3_client.get_waiter('bucket_not_exists').wait(Bucket=name,
                                                       WaiterConfig=dict(
                                                           Delay=5,
                                                           MaxAttempts=60))
    except WaiterError as e:
        module.fail_json_aws(
            e, msg='An error occurred waiting for the bucket to be deleted.')
    except (BotoCoreError, ClientError) as e:
        module.fail_json_aws(e, msg="Failed to delete bucket")

    module.exit_json(changed=True)
Ejemplo n.º 19
0
    def send_request(self, request_method, path, payload=None):
        data = json.dumps(payload) if payload else '{}'

        try:
            self._display_request(request_method)
            response, response_data = self.connection.send(path, payload, method=request_method, headers=BASE_HEADERS, force_basic_auth=True)
            value = self._get_response_value(response_data)

            return response.getcode(), self._response_to_json(value)
        except AnsibleConnectionFailure as e:
            if to_text('401') in to_text(e):
                return 401, 'Authentication failure'
            else:
                return 404, 'Object not found'
        except HTTPError as e:
            error = json.loads(e.read())
            return e.code, error
Ejemplo n.º 20
0
    def handle_httperror(self, exc):
        """
        propogate exceptions to users
        :param exc: Exception
        """
        self.log('Exception thrown from handling http: ' + to_text(exc))

        return exc
Ejemplo n.º 21
0
def decode_rules_as_hcl_string(rules_as_hcl):
    """
    Converts the given HCL (string) representation of rules into a list of rule domain models.
    :param rules_as_hcl: the HCL (string) representation of a collection of rules
    :return: the equivalent domain model to the given rules
    """
    rules_as_hcl = to_text(rules_as_hcl)
    rules_as_json = hcl.loads(rules_as_hcl)
    return decode_rules_as_json(rules_as_json)
Ejemplo n.º 22
0
def decode_rules_as_hcl_string(rules_as_hcl):
    """
    Converts the given HCL (string) representation of rules into a list of rule domain models.
    :param rules_as_hcl: the HCL (string) representation of a collection of rules
    :return: the equivalent domain model to the given rules
    """
    rules_as_hcl = to_text(rules_as_hcl)
    rules_as_json = hcl.loads(rules_as_hcl)
    return decode_rules_as_json(rules_as_json)
Ejemplo n.º 23
0
    def send_request(self, request_method, path, payload=None, headers=None, basic_auth=False, **kwargs):
        headers = headers if headers else BASE_HEADERS
        # space platform API endpoints which are asyncrhonous require basic_auth and no JSESSIONID cookies set.
        if basic_auth:
            self.connection._auth = None

        try:
            self._display_request(request_method)
            response, response_data = self.connection.send(path, payload, method=request_method, headers=headers, **kwargs)
            value = self._get_response_value(response_data)
            return response.getcode(), self._response_to_json(value)
        except AnsibleConnectionFailure as e:
            if to_text('401') in to_text(e):
                return 401, 'Authentication failure'
            else:
                return 404, 'Object not found'
        except HTTPError as e:
            error = json.loads(e.read())
            return e.code, error
Ejemplo n.º 24
0
 def update_system_version(self):
     """
     retrieve the system status of fortigate device
     """
     url = '/api/v2/cmdb/system/interface?vdom=root&action=schema'
     status, result = self.send_request(url=url)
     self.log('update sys ver: ' + str(status) + ' len=' + str(len(to_text(result))))
     result_json = json.loads(result)
     self._system_version = result_json.get('version', 'undefined')
     self.log('system version: %s' % (self._system_version))
     self.log('ansible version: %s' % (self._ansible_fos_version))
Ejemplo n.º 25
0
 def _send_service_request(self, path, error_msg_prefix, data=None, **kwargs):
     try:
         self._ignore_http_errors = True
         return self.connection.send(path, data, **kwargs)
     except HTTPError as e:
         # HttpApi connection does not read the error response from HTTPError, so we do it here and wrap it up in
         # ConnectionError, so the actual error message is displayed to the user.
         error_msg = self._response_to_json(to_text(e.read()))
         raise ConnectionError('%s: %s' % (error_msg_prefix, error_msg), http_code=e.code)
     finally:
         self._ignore_http_errors = False
Ejemplo n.º 26
0
def paginated_versioned_list_with_fallback(s3, **pagination_params):
    try:
        versioned_pg = s3.get_paginator('list_object_versions')
        for page in versioned_pg.paginate(**pagination_params):
            delete_markers = [{'Key': data['Key'], 'VersionId': data['VersionId']} for data in page.get('DeleteMarkers', [])]
            current_objects = [{'Key': data['Key'], 'VersionId': data['VersionId']} for data in page.get('Versions', [])]
            yield delete_markers + current_objects
    except botocore.exceptions.ClientError as e:
        if to_text(e.response['Error']['Code']) in IGNORE_S3_DROP_IN_EXCEPTIONS + ['AccessDenied']:
            for page in paginated_list(s3, **pagination_params):
                yield [{'Key': data['Key']} for data in page]
Ejemplo n.º 27
0
 def _send_auth_request(self, path, data, **kwargs):
     try:
         self._ignore_http_errors = True
         return self.connection.send(path, data, **kwargs)
     except HTTPError as e:
         # HttpApi connection does not read the error response from HTTPError, so we do it here and wrap it up in
         # ConnectionError, so the actual error message is displayed to the user.
         error_msg = self._response_to_json(to_text(e.read()))
         raise ConnectionError('Server returned an error during authentication request: %s' % error_msg)
     finally:
         self._ignore_http_errors = False
Ejemplo n.º 28
0
    def send_request(self, **message_kwargs):
        """
        Responsible for actual sending of data to the connection httpapi base plugin.
        :param message_kwargs: A formatted dictionary containing request info: url, data, method

        :return: Status code and response data.
        """

        url = message_kwargs.get('url', '/')
        if self.get_access_token() is not None:
            url = self._concat_token(message_kwargs.get('url', '/'))
        data = message_kwargs.get('data', '')
        method = message_kwargs.get('method', 'GET')
        params = message_kwargs.get('params', {})

        url = self._concat_params(url, params)
        self.log('send request: METHOD:%s URL:%s DATA:%s' %
                 (method, url, to_text(data)[:100] + "..."))
        try:
            response, response_data = self.connection.send(url,
                                                           data,
                                                           method=method)

            response_text = to_text(response_data.getvalue())

            self.log('whole response for METHOD:%s URL:%s ' % (method, url))
            self.log(to_text(response.headers['Content-Type']))
            self.log(response.status)
            self.log(response_text[:100])
            if response.headers['Content-Type'] == "application/json":
                return response.status, response_text
            else:
                ## convert raw text responses into a json string for some APIs like config/backup
                return response.status, json.dumps({
                    'text':
                    response_text,
                    'http_status':
                    response.status
                })
        except Exception as err:
            raise Exception(err)
    def test_send_request(self, params, headers, data):
        self.connection_mock.send.return_value = self._send_response(
            200,
            "<request status='success'></request>",
        )

        (code, response) = self.plugin.send_request(data=data,
                                                    params=params,
                                                    headers=headers)

        assert code == 200
        assert "success" in to_text(response)
Ejemplo n.º 30
0
    def send_request(self, request_method, path, data={}):
        '''Prepares, sends and format resonse of Contrail API requests.

        :param str request_method: HTTP method
        :param str path: API path
        :param dict data: Request data, serializable as JSON

        :return: A tuple as (status_code: int, content: dict)
        :rtype: tuple
        '''
        # Contrail API call may fail, and response may be empty or not in JSON format.
        # In such cases, a **custom** JSON content is returned as { "message": "..." }
        try:
            response, response_data = self.connection.send(
                path,
                json.dumps(data),
                method=request_method,
                headers=BASE_HEADERS)
            # Request succeed
            if response.getcode() in [
                    200,
            ]:
                try:
                    content = json.loads(to_text(response_data.getvalue()))
                # Request succeed, but response not in JSON -> Generate custom response content
                except Exception:
                    content = {"message": to_text(response_data.getvalue())}
                return response.getcode(), content
            # Request failed -> Generate custom response content
            else:
                return response.getcode(), {
                    "message": to_text(response_data.getvalue())
                }
        # Generic errors -> Generate custom response content
        except AnsibleConnectionFailure as error:
            if to_text('401') in to_text(error):
                return 401, {"message": "Authentication failure"}
        except HTTPError as error:
            return error.code, json.loads(error.read())
 def get_adom_list(self):
     """
     Gets the list of ADOMs for the FortiManager
     """
     if self._uses_adoms:
         url = "/dvmdb/adom"
         datagram = {}
         data = self._tools.format_request(FMGRMethods.GET, url, **datagram)
         resp_obj = self.send_request(FMGRMethods.GET, data)
         code = resp_obj[0]
         if code != 0:
             self._module.fail_json(msg=("An error occurred trying to get the ADOM Info. "
                                         "Error: " + to_text(resp_obj)))
         elif code == 0:
             num_of_adoms = len(resp_obj[1]['data'])
             append_list = ['root', 'global']
             for adom in resp_obj[1]['data']:
                 if adom["tab_status"] != "":
                     append_list.append(to_text(adom["name"]))
             self._adom_list = append_list
         self.log('adom list: %s' % (str(self._adom_list)))
         return resp_obj
Ejemplo n.º 32
0
def handle_errors(error):
    try:
        error_data = json.loads(error.read())
    except ValueError:
        error_data = error.read()

    if error_data:
        if "errors" in error_data:
            errors = error_data["errors"]["error"]
            error_text = "\n".join(
                (error["error-message"] for error in errors)
            )
        else:
            error_text = error_data
        return error_text
    return to_text(error)
Ejemplo n.º 33
0
def bucket_check(module, s3, bucket, validate=True):
    exists = True
    try:
        s3.head_bucket(Bucket=bucket)
    except botocore.exceptions.ClientError as e:
        # If a client error is thrown, then check that it was a 404 error.
        # If it was a 404 error, then the bucket does not exist.
        error_code = int(e.response['Error']['Code'])
        if error_code == 404:
            exists = False
        elif error_code == 403 and validate is False:
            pass
        else:
            module.fail_json(msg="Failed while looking up bucket (during bucket_check) %s." % bucket,
                             exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
    except botocore.exceptions.EndpointConnectionError as e:
        module.fail_json(msg="Invalid endpoint provided: %s" % to_text(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
    return exists
Ejemplo n.º 34
0
def get_s3_client(module, aws_connect_kwargs, location, ceph, s3_url):
    if s3_url and ceph:  # TODO - test this
        ceph = urlparse(s3_url)
        params = dict(module=module, conn_type='client', resource='s3', use_ssl=ceph.scheme == 'https', region=location, endpoint=s3_url, **aws_connect_kwargs)
    elif is_fakes3(s3_url):
        fakes3 = urlparse(s3_url)
        port = fakes3.port
        if fakes3.scheme == 'fakes3s':
            protocol = "https"
            if port is None:
                port = 443
        else:
            protocol = "http"
            if port is None:
                port = 80
        params = dict(module=module, conn_type='client', resource='s3', region=location,
                      endpoint="%s://%s:%s" % (protocol, fakes3.hostname, to_text(port)),
                      use_ssl=fakes3.scheme == 'fakes3s', **aws_connect_kwargs)
    elif is_walrus(s3_url):
        walrus = urlparse(s3_url).hostname
        params = dict(module=module, conn_type='client', resource='s3', region=location, endpoint=walrus, **aws_connect_kwargs)
    else:
        params = dict(module=module, conn_type='client', resource='s3', region=location, endpoint=s3_url, **aws_connect_kwargs)
    return boto3_conn(**params)
Ejemplo n.º 35
0
def get_s3_connection(module, aws_connect_kwargs, location, rgw, s3_url):
    if s3_url and rgw:  # TODO - test this
        rgw = urlparse(s3_url)
        params = dict(module=module, conn_type='client', resource='s3', use_ssl=rgw.scheme == 'https', region=location, endpoint=s3_url, **aws_connect_kwargs)
    elif is_fakes3(s3_url):
        for kw in ['is_secure', 'host', 'port'] and list(aws_connect_kwargs.keys()):
            del aws_connect_kwargs[kw]
        fakes3 = urlparse(s3_url)
        if fakes3.scheme == 'fakes3s':
            protocol = "https"
        else:
            protocol = "http"
        params = dict(service_name='s3', endpoint_url="%s://%s:%s" % (protocol, fakes3.hostname, to_text(fakes3.port)),
                      use_ssl=fakes3.scheme == 'fakes3s', region_name=None, **aws_connect_kwargs)
    elif is_walrus(s3_url):
        walrus = urlparse(s3_url).hostname
        params = dict(module=module, conn_type='client', resource='s3', region=location, endpoint=walrus, **aws_connect_kwargs)
    else:
        params = dict(module=module, conn_type='client', resource='s3', region=location, endpoint=s3_url, **aws_connect_kwargs)
    return boto3_conn(**params)
Ejemplo n.º 36
0
def create_or_update_bucket(s3_client, module, location):

    policy = module.params.get("policy")
    name = module.params.get("name")
    requester_pays = module.params.get("requester_pays")
    tags = module.params.get("tags")
    versioning = module.params.get("versioning")
    changed = False

    try:
        bucket_is_present = bucket_exists(s3_client, name)
    except EndpointConnectionError as e:
        module.fail_json_aws(e, msg="Invalid endpoint provided: %s" % to_text(e))
    except (BotoCoreError, ClientError) as e:
        module.fail_json_aws(e, msg="Failed to check bucket presence")

    if not bucket_is_present:
        try:
            bucket_changed = create_bucket(s3_client, name, location)
            s3_client.get_waiter('bucket_exists').wait(Bucket=name)
            changed = changed or bucket_changed
        except WaiterError as e:
            module.fail_json_aws(e, msg='An error occurred waiting for the bucket to become available')
        except (BotoCoreError, ClientError) as e:
            module.fail_json_aws(e, msg="Failed while creating bucket")

    # Versioning
    try:
        versioning_status = get_bucket_versioning(s3_client, name)
    except (ClientError, BotoCoreError) as e:
        module.fail_json_aws(e, msg="Failed to get bucket versioning")

    if versioning is not None:
        required_versioning = None
        if versioning and versioning_status.get('Status') != "Enabled":
            required_versioning = 'Enabled'
        elif not versioning and versioning_status.get('Status') == "Enabled":
            required_versioning = 'Suspended'

        if required_versioning:
            try:
                put_bucket_versioning(s3_client, name, required_versioning)
                changed = True
            except (BotoCoreError, ClientError) as e:
                module.fail_json_aws(e, msg="Failed to update bucket versioning")

            versioning_status = wait_versioning_is_applied(module, s3_client, name, required_versioning)

    # This output format is there to ensure compatibility with previous versions of the module
    versioning_return_value = {
        'Versioning': versioning_status.get('Status', 'Disabled'),
        'MfaDelete': versioning_status.get('MFADelete', 'Disabled'),
    }

    # Requester pays
    try:
        requester_pays_status = get_bucket_request_payment(s3_client, name)
    except (BotoCoreError, ClientError) as e:
        module.fail_json_aws(e, msg="Failed to get bucket request payment")

    payer = 'Requester' if requester_pays else 'BucketOwner'
    if requester_pays_status != payer:
        put_bucket_request_payment(s3_client, name, payer)
        requester_pays_status = wait_payer_is_applied(module, s3_client, name, payer, should_fail=False)
        if requester_pays_status is None:
            # We have seen that it happens quite a lot of times that the put request was not taken into
            # account, so we retry one more time
            put_bucket_request_payment(s3_client, name, payer)
            requester_pays_status = wait_payer_is_applied(module, s3_client, name, payer, should_fail=True)
        changed = True

    # Policy
    try:
        current_policy = get_bucket_policy(s3_client, name)
    except (ClientError, BotoCoreError) as e:
        module.fail_json_aws(e, msg="Failed to get bucket policy")

    if policy is not None:
        if isinstance(policy, string_types):
            policy = json.loads(policy)

        if not policy and current_policy:
            try:
                delete_bucket_policy(s3_client, name)
            except (BotoCoreError, ClientError) as e:
                module.fail_json_aws(e, msg="Failed to delete bucket policy")
            current_policy = wait_policy_is_applied(module, s3_client, name, policy)
            changed = True
        elif compare_policies(current_policy, policy):
            try:
                put_bucket_policy(s3_client, name, policy)
            except (BotoCoreError, ClientError) as e:
                module.fail_json_aws(e, msg="Failed to update bucket policy")
            current_policy = wait_policy_is_applied(module, s3_client, name, policy, should_fail=False)
            if current_policy is None:
                # As for request payement, it happens quite a lot of times that the put request was not taken into
                # account, so we retry one more time
                put_bucket_policy(s3_client, name, policy)
                current_policy = wait_policy_is_applied(module, s3_client, name, policy, should_fail=True)
            changed = True

    # Tags
    try:
        current_tags_dict = get_current_bucket_tags_dict(s3_client, name)
    except (ClientError, BotoCoreError) as e:
        module.fail_json_aws(e, msg="Failed to get bucket tags")

    if tags is not None:
        if current_tags_dict != tags:
            if tags:
                try:
                    put_bucket_tagging(s3_client, name, tags)
                except (BotoCoreError, ClientError) as e:
                    module.fail_json_aws(e, msg="Failed to update bucket tags")
            else:
                try:
                    delete_bucket_tagging(s3_client, name)
                except (BotoCoreError, ClientError) as e:
                    module.fail_json_aws(e, msg="Failed to delete bucket tags")
            wait_tags_are_applied(module, s3_client, name, tags)
            current_tags_dict = tags
            changed = True

    module.exit_json(changed=changed, name=name, versioning=versioning_return_value,
                     requester_pays=requester_pays, policy=current_policy, tags=current_tags_dict)