Beispiel #1
0
def validate_object_id(object_id):
    """Validates object ID (server_id, policy_id, etc...)

    This function validates Object IDs with the intent of guarding against \
    URL traversal.

    Args:
        object_id (str or list): Object ID to be validated

    Returns:
        (bool) True if valid, throws an exception otherwise.

    """

    rex = re.compile('^[A-Za-z0-9]+$')
    if isinstance(object_id, (str, unicode)):
        if not rex.match(object_id):
            error_message = "Object ID failed validation: %s" % object_id
            raise CloudPassageValidation(error_message)
        else:
            return True
    elif isinstance(object_id, list):
        for individual in object_id:
            if not rex.match(individual):
                error_message = "Object ID failed validation: %s" % object_id
                raise CloudPassageValidation(error_message)
        return True
    else:
        error_message = "Wrong type for object ID: %s" % str(type(object_id))
        raise TypeError(error_message)
 def verify_and_build_module_params(self, module_raw):
     """Verifies module params and data types"""
     if isinstance(module_raw, list):
         for module in module_raw:
             if self.scan_type_supported(module) is not True:
                 exception_message = "%s is not supported" % module
                 raise CloudPassageValidation(exception_message)
     else:
         if self.scan_type_supported(module_raw) is False:
             error_message = "Unsupported module: %s" % module_raw
             raise CloudPassageValidation(error_message)
     return module_raw
 def verify_and_build_status_params(self, status_raw):
     """Verifies status params and data types."""
     if isinstance(status_raw, list):
         for status in status_raw:
             if self.scan_status_supported(status) is not True:
                 exception_message = "%s is not supported" % status
                 raise CloudPassageValidation(exception_message)
     else:
         if self.scan_status_supported(status_raw) is False:
             error_message = "Unsupported status: %s" % status_raw
             raise CloudPassageValidation(error_message)
     return status_raw
    def last_scan_results(self, server_id, scan_type):
        """Get the results of scan_type performed on server_id.

        Args:
            server_id (str): ID of server
            scan_type (str): Type of scan to filter results for

        Valid scan types:
          sca  - Configuration scan
          csm  - Configuration scan (same as sca)
          svm  - Software vulnerability scan
          sva  - Software vulnerability scan (same as svm)
          fim  - File integrity monitoring scan

        Returns:
            dict: Dictionary object describing last scan results

        """

        if self.scan_history_supported(scan_type) is False:
            exception_message = "Unsupported scan type: %s" % scan_type
            raise CloudPassageValidation(exception_message)
        else:
            scan_type_normalized = self.supported_scans[scan_type]
            endpoint = "/v1/servers/%s/%s" % (server_id, scan_type_normalized)
            request = HttpHelper(self.session)
            response = request.get(endpoint)
            return response
    def initiate_scan(self, server_id, scan_type):
        """Initiate a scan on a specific server.

        Args:
            server_id (str): ID of server to be scanned
            scan_type (str): Type of scan to be run.

          Valid scan types:
            sca  - Configuration scan
            csm  - Configuration scan (same as sca)
            svm  - Software vulnerability scan
            sva  - Software vulnerability scan (same as svm)
            sam  - Server access management scan
            fim  - File integrity monitoring scan
            sv   - Agent self-verifiation scan

        Returns:
            dict: Dictionary describing command created as a result of this \
            call
            Failure throws an exception.
        """

        sanity.validate_object_id(server_id)
        if self.scan_type_supported(scan_type) is False:
            exception_message = "Unsupported scan type: %s" % scan_type
            raise CloudPassageValidation(exception_message)
        else:
            scan_type_normalized = self.supported_scans[scan_type]
            request_body = {"scan": {"module": scan_type_normalized}}
            endpoint = "/v1/servers/%s/scans" % server_id
            request = HttpHelper(self.session)
            response = request.post(endpoint, request_body)
            command_info = response["command"]
            return command_info
Beispiel #6
0
    def build_endpoint_prefix(self):
        """This constructs everything to the left of the file path in the URL.

        """
        if not sanity.validate_api_hostname(self.api_host):
            error_message = "Bad API hostname: %s" % self.api_host
            raise CloudPassageValidation(error_message)
        prefix = "https://" + self.api_host + ":" + str(self.api_port)
        return prefix
Beispiel #7
0
def parse_status(url, resp_code, resp_text):
    """Parse status from HTTP response"""
    success = True
    exc = None
    if resp_code not in [200, 201, 202, 204]:
        success = False
        bad_statuses = {
            400: CloudPassageValidation(resp_text, code=400),
            401: CloudPassageAuthentication(resp_text, code=401),
            404: CloudPassageResourceExistence(resp_text, code=404, url=url),
            403: CloudPassageAuthorization(resp_text, code=403),
            422: CloudPassageValidation(resp_text, code=422)
        }
        if resp_code in bad_statuses:
            return (success, bad_statuses[resp_code])
        else:
            return (success, CloudPassageGeneral(resp_text, code=resp_code))
    return success, exc
    def get_paginated(self, endpoint, key, max_pages, **kwargs):
        """This method returns a concatenated list of objects
        from the Halo API.

        It's really a wrapper for the get() method.  Pass in the
        path as with the get() method, and a maxpages number.
        Maxpages is expected to be an integer between 2 and 100

        Args:
            endpoint (str): Path for initial query
            key (str): The key in the response containing the objects \
            of interest.  For instance, the /v1/events endpoint will \
            have the "events" key, which contains a list of dictionary \
            objects representing Halo events.
            maxpages (int): This is a number from 2-100.  More than 100 pages \
            can take quite a while to return, so beyond that you should \
            consider using this SDK as a component in a multi-threaded tool.
        Keyword Args:
            params (list of dict): This is a list of dictionary objects, \
            represented like this: [{"k1": "two,too"}] \
            which goes into the URL looking like this: ?k1=two,too . \
            If you use a list as the value in a dictionary here, you'll get \
            two k/v pairs represented in the URL and the CloudPassage API \
            doesn't operate like that.  Only the last instance of that \
            variable will be considered, and your results may be confusing.  \
            So don't do it.  Dictionaries should be {str:str}.

        """

        max_pages_valid, pages_invalid_msg = utility.verify_pages(max_pages)
        if not max_pages_valid:
            raise CloudPassageValidation(pages_invalid_msg)
        more_pages = False
        response_accumulator = []
        if "params" in kwargs and kwargs["params"] is not {}:
            initial_page = self.get(endpoint, params=kwargs["params"])
        else:
            initial_page = self.get(endpoint)
        response, next_page = self.process_page(initial_page, key)
        response_accumulator.extend(response)
        pages_parsed = 1
        if next_page is not None:
            more_pages = True
        while more_pages:
            page = self.get(next_page)
            response, next_page = self.process_page(page, key)
            response_accumulator.extend(response)
            pages_parsed += 1
            if next_page is None:
                more_pages = False
            if pages_parsed >= max_pages:
                more_pages = False
        return response_accumulator
 def process_page(cls, page, key):
     """Page goes in, list data comes out."""
     response_accumulator = []
     next_page = None
     if key not in page:
         fail_msg = ("Requested key %s not found in page" % key)
         raise CloudPassageValidation(fail_msg)
     for k in page[key]:
         response_accumulator.append(k)
     if "pagination" in page:
         if "next" in page["pagination"]:
             nextpage = page["pagination"]["next"]
             endpoint = str(
                 urlparse.urlsplit(nextpage)[2] + "?" +
                 urlparse.urlsplit(nextpage)[3])
             next_page = endpoint
     return response_accumulator, next_page
 def raise_validation(self, msg):
     raise CloudPassageValidation(msg)