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
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