def get_excluded_paths(self):
     repo_settings_api_url = f'{self.api_url}/api/v1/vcs/settings/scheme'
     try:
         request = self.http.request(
             "GET",
             repo_settings_api_url,
             headers=merge_dicts(
                 {
                     "Authorization": self.get_auth_token(),
                     "Content-Type": "application/json"
                 }, get_user_agent_header()))
         response = json.loads(request.data.decode("utf8"))
         if 'scannedFiles' in response:
             for section in response.get('scannedFiles').get('sections'):
                 if self.repo_id in section.get('repos') and section.get(
                         'rule').get('excludePaths'):
                     self.excluded_paths.extend(
                         section.get('rule').get('excludePaths'))
         return self.excluded_paths
     except HTTPError as e:
         logging.error(
             f"Failed to get vcs settings for repo {self.repo_path}\n{e}")
         raise e
     except JSONDecodeError as e:
         logging.error(
             f"Response of {repo_settings_api_url} is not a valid JSON\n{e}"
         )
         raise e
 def get_checkov_mapping_metadata(self) -> None:
     if self.bc_skip_mapping is True:
         logging.debug("Skipped mapping API call")
         self.ckv_to_bc_id_mapping = {}
         return
     guidelines_url = self.guidelines_api_url
     headers = get_user_agent_header()
     try:
         if (self.bc_api_key is not None):
             guidelines_url = self.customer_all_guidelines_api_url
             headers = merge_dicts(
                 headers, {
                     "Authorization": self.get_auth_token(),
                     "Content-Type": "application/json"
                 })
         if not self.http:
             self.setup_http_manager()
         request = self.http.request("GET", guidelines_url, headers=headers)
         response = json.loads(request.data.decode("utf8"))
         self.guidelines = response["guidelines"]
         self.bc_id_mapping = response.get("idMapping")
         self.ckv_to_bc_id_mapping = {
             ckv_id: bc_id
             for (bc_id, ckv_id) in self.bc_id_mapping.items()
         }
         logging.debug("Got checkov mappings from Bridgecrew BE")
     except Exception as e:
         logging.debug(
             f"Failed to get the guidelines from {guidelines_url}, error:\n{e}"
         )
         self.ckv_to_bc_id_mapping = {}
         return
 def get_auth_token(self) -> str:
     if self.is_bc_token(self.bc_api_key):
         return self.bc_api_key
     # A Prisma Cloud Access Key was specified as the Bridgecrew token.
     if not self.prisma_api_url:
         raise ValueError(
             "A Prisma Cloud token was set, but no Prisma Cloud API URL was set"
         )
     if '::' not in self.bc_api_key:
         raise ValueError(
             "A Prisma Cloud token was set, but the token is not in the correct format: <access_key_id>::<secret_key>"
         )
     username, password = self.bc_api_key.split('::')
     request = self.http.request("POST",
                                 f"{self.prisma_api_url}/login",
                                 body=json.dumps({
                                     "username": username,
                                     "password": password
                                 }),
                                 headers=merge_dicts(
                                     {"Content-Type": "application/json"},
                                     get_user_agent_header()))
     if request.status == 401:
         raise BridgecrewAuthError()
     token = json.loads(request.data.decode("utf8"))['token']
     return token
    def get_s3_role(self, repo_id):
        token = self.get_auth_token()
        request = self.http.request("POST",
                                    self.integrations_api_url,
                                    body=json.dumps({"repoId": repo_id}),
                                    headers=merge_dicts(
                                        {
                                            "Authorization": token,
                                            "Content-Type": "application/json"
                                        }, get_user_agent_header()))
        if request.status == 403:
            raise BridgecrewAuthError()
        response = json.loads(request.data.decode("utf8"))
        while ('Message' in response or 'message' in response):
            if 'Message' in response and response[
                    'Message'] == UNAUTHORIZED_MESSAGE:
                raise BridgecrewAuthError()
            if 'message' in response and ASSUME_ROLE_UNUATHORIZED_MESSAGE in response[
                    'message']:
                raise BridgecrewAuthError(
                    "Checkov got an unexpected authorization error that may not be due to your credentials. Please contact support."
                )
            if 'message' in response and "cannot be found" in response[
                    'message']:
                self.loading_output("creating role")
                request = self.http.request(
                    "POST",
                    self.integrations_api_url,
                    body=json.dumps({"repoId": repo_id}),
                    headers=merge_dicts(
                        {
                            "Authorization": token,
                            "Content-Type": "application/json"
                        }, get_user_agent_header()))
                response = json.loads(request.data.decode("utf8"))

        repo_full_path = response["path"]
        return repo_full_path, response
Beispiel #5
0
 def _headers(self):
     return merge_dicts(
         {
             "Accept": "application/vnd.github.v3+json",
             "Authorization": "token {}".format(self.token)
         }, get_user_agent_header())
    def commit_repository(self, branch):
        """
        :param branch: branch to be persisted
        Finalize the repository's scanning in bridgecrew's platform.
        """
        try_num = 0
        while try_num < MAX_RETRIES:
            if not self.use_s3_integration:
                return

            request = None
            response = None
            try:

                request = self.http.request(
                    "PUT",
                    f"{self.integrations_api_url}?source={self.bc_source.name}",
                    body=json.dumps({
                        "path": self.repo_path,
                        "branch": branch,
                        "to_branch": BC_TO_BRANCH,
                        "pr_id": BC_PR_ID,
                        "pr_url": BC_PR_URL,
                        "commit_hash": BC_COMMIT_HASH,
                        "commit_url": BC_COMMIT_URL,
                        "author": BC_AUTHOR_NAME,
                        "author_url": BC_AUTHOR_URL,
                        "run_id": BC_RUN_ID,
                        "run_url": BC_RUN_URL,
                        "repository_url": BC_REPOSITORY_URL
                    }),
                    headers=merge_dicts(
                        {
                            "Authorization": self.get_auth_token(),
                            "Content-Type": "application/json",
                            'x-api-client': self.bc_source.name,
                            'x-api-checkov-version': checkov_version
                        }, get_user_agent_header()))
                response = json.loads(request.data.decode("utf8"))
                url = response.get("url", None)
                return url
            except HTTPError as e:
                logging.error(
                    f"Failed to commit repository {self.repo_path}\n{e}")
                raise e
            except JSONDecodeError as e:
                logging.error(
                    f"Response of {self.integrations_api_url} is not a valid JSON\n{e}"
                )
                raise e
            finally:
                if request.status == 201 and response and response.get(
                        "result") == "Success":
                    logging.info(
                        f"Finalize repository {self.repo_id} in bridgecrew's platform"
                    )
                elif try_num < MAX_RETRIES and re.match(
                        'The integration ID .* in progress',
                        response.get('message', '')):
                    logging.info(
                        f"Failed to persist for repo {self.repo_id}, sleeping for {SLEEP_SECONDS} seconds before retrying"
                    )
                    try_num += 1
                    sleep(SLEEP_SECONDS)
                else:
                    raise Exception(
                        f"Failed to finalize repository {self.repo_id} in bridgecrew's platform\n{response}"
                    )
ACCOUNT_CREATION_TIME = 180  # in seconds

UNAUTHORIZED_MESSAGE = 'User is not authorized to access this resource with an explicit deny'
ASSUME_ROLE_UNUATHORIZED_MESSAGE = 'is not authorized to perform: sts:AssumeRole'

FileToPersist = namedtuple('FileToPersist', 'full_file_path s3_file_key')

DEFAULT_REGION = "us-west-2"
MAX_RETRIES = 40
ONBOARDING_SOURCE = "checkov"

SIGNUP_HEADER = merge_dicts(
    {
        'Accept': 'application/json',
        'Content-Type': 'application/json;charset=UTF-8'
    }, get_user_agent_header())


class BcPlatformIntegration(object):
    def __init__(self):
        self.bc_api_key = read_key()
        self.s3_client = None
        self.bucket = None
        self.credentials = None
        self.repo_path = None
        self.repo_id = None
        self.repo_branch = None
        self.skip_fixes = False
        self.skip_suppressions = False
        self.skip_policy_download = False
        self.timestamp = None