def circle_ci_range(verbose: bool) -> List[str]: # pragma: no cover """ # Extract commit range (or single commit) COMMIT_RANGE=$(echo "${CIRCLE_COMPARE_URL}" | cut -d/ -f7) # Fix single commit, unfortunately we don't always get a commit range from Circle CI if [[ $COMMIT_RANGE != *"..."* ]]; then COMMIT_RANGE="${COMMIT_RANGE}...${COMMIT_RANGE}" fi """ compare_range = os.getenv("CIRCLE_RANGE") commit_sha = os.getenv("CIRCLE_SHA1", "HEAD") if verbose: click.echo(f"CIRCLE_RANGE: {compare_range}\nCIRCLE_SHA1: {commit_sha}") if compare_range and not compare_range.startswith("..."): commit_list = get_list_commit_SHA(compare_range) if commit_list: return commit_list commit_list = get_list_commit_SHA("{}~1...".format(commit_sha)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" "\tRepository URL: <Fill if public>\n" f"\tCIRCLE_RANGE: {compare_range}\n" f"\tCIRCLE_SHA1: {commit_sha}")
def gitlab_ci_range(verbose: bool) -> List[str]: # pragma: no cover before_sha = os.getenv("CI_COMMIT_BEFORE_SHA") commit_sha = os.getenv("CI_COMMIT_SHA", "HEAD") merge_request_target_branch = os.getenv( "CI_MERGE_REQUEST_TARGET_BRANCH_NAME") if verbose: click.echo( f"CI_MERGE_REQUEST_TARGET_BRANCH_NAME: {merge_request_target_branch}\n" f"CI_COMMIT_BEFORE_SHA: {before_sha}\n" f"CI_COMMIT_SHA: {commit_sha}") if before_sha and before_sha != EMPTY_SHA: commit_list = get_list_commit_SHA("{}~1...".format(before_sha)) if commit_list: return commit_list if merge_request_target_branch and merge_request_target_branch != EMPTY_SHA: commit_list = get_list_commit_SHA( "origin/{}...".format(merge_request_target_branch)) if commit_list: return commit_list commit_list = get_list_commit_SHA("{}~1...".format(commit_sha)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" " Repository URL: <Fill if public>\n" f" CI_MERGE_REQUEST_TARGET_BRANCH_NAME: {merge_request_target_branch}\n" f" CI_COMMIT_BEFORE_SHA: {before_sha}\n" f" CI_COMMIT_SHA: {commit_sha}")
def scan_repo_path( client: GGClient, cache: Cache, output_handler: OutputHandler, config: Config, repo_path: str, scan_id: str, ) -> int: # pragma: no cover try: with cd(repo_path): if not is_git_dir(): raise click.ClickException( f"{repo_path} is not a git repository") return scan_commit_range( client=client, cache=cache, commit_list=get_list_commit_SHA("--all"), output_handler=output_handler, verbose=config.verbose, exclusion_regexes=set(), matches_ignore=config.matches_ignore, all_policies=config.all_policies, scan_id=scan_id, mode_header=SupportedScanMode.REPO.value, banlisted_detectors=config.banlisted_detectors, ) except Exception as error: return handle_exception(error, config.verbose)
def github_actions_range(verbose: bool) -> List[str]: # pragma: no cover push_before_sha = os.getenv("GITHUB_PUSH_BEFORE_SHA") push_base_sha = os.getenv("GITHUB_PUSH_BASE_SHA") pull_req_base_sha = os.getenv("GITHUB_PULL_BASE_SHA") default_branch = os.getenv("GITHUB_DEFAULT_BRANCH") head_sha = os.getenv("GITHUB_SHA", "HEAD") if verbose: click.echo(f"github_push_before_sha: {push_before_sha}\n" f"github_push_base_sha: {push_base_sha}\n" f"github_pull_base_sha: {pull_req_base_sha}\n" f"github_default_branch: {default_branch}\n" f"github_head_sha: {head_sha}") if push_before_sha and push_before_sha != EMPTY_SHA: commit_list = get_list_commit_SHA("{}...".format(push_before_sha)) if commit_list: return commit_list if pull_req_base_sha and pull_req_base_sha != EMPTY_SHA: commit_list = get_list_commit_SHA("{}..".format(pull_req_base_sha)) if commit_list: return commit_list if push_base_sha and push_base_sha != "null": commit_list = get_list_commit_SHA("{}...".format(push_base_sha)) if commit_list: return commit_list if default_branch: commit_list = get_list_commit_SHA("{}...".format(default_branch)) if commit_list: return commit_list if head_sha: commit_list = get_list_commit_SHA("{}~1...".format(head_sha)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" " Repository URL: <Fill if public>\n" f"github_push_before_sha: {push_before_sha}\n" f"github_push_base_sha: {push_base_sha}\n" f"github_pull_base_sha: {pull_req_base_sha}" f"github_default_branch: {default_branch}\n" f"github_head_sha: {head_sha}")
def bitbucket_pipelines_range(verbose: bool) -> List[str]: # pragma: no cover commit_sha = os.getenv("BITBUCKET_COMMIT", "HEAD") if verbose: click.echo(f"BITBUCKET_COMMIT: {commit_sha}") commit_list = get_list_commit_SHA("{}~1...".format(commit_sha)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" " Repository URL: <Fill if public>\n" f" CI_COMMIT_SHA: {commit_sha}")
def travis_range(verbose: bool) -> List[str]: # pragma: no cover commit_range = os.getenv("TRAVIS_COMMIT_RANGE") commit_sha = os.getenv("TRAVIS_COMMIT", "HEAD") if verbose: click.echo(f"TRAVIS_COMMIT_RANGE: {commit_range}" f"\nTRAVIS_COMMIT: {commit_sha}") if commit_range: commit_list = get_list_commit_SHA(commit_range) if commit_list: return commit_list commit_list = get_list_commit_SHA("{}~1...".format(commit_sha)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" "\tRepository URL: <Fill if public>\n" f"\tTRAVIS_COMMIT_RANGE: {commit_range}" f"\tTRAVIS_COMMIT: {commit_sha}")
def jenkins_range(verbose: bool) -> List[str]: # pragma: no cover head_commit = os.getenv("GIT_COMMIT") previous_commit = os.getenv("GIT_PREVIOUS_COMMIT") if verbose: click.echo(f"\tGIT_COMMIT: {head_commit}" f"\nGIT_PREVIOUS_COMMIT: {previous_commit}") if previous_commit: commit_list = get_list_commit_SHA(f"{previous_commit}...{head_commit}") if commit_list: return commit_list commit_list = get_list_commit_SHA(f"{head_commit}~1...") if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" "\tRepository URL: <Fill if public>\n" f"\tGIT_COMMIT: {head_commit}" f"\tGIT_PREVIOUS_COMMIT: {previous_commit}")
def azure_range(verbose: bool) -> List[str]: # pragma: no cover head_commit = os.getenv("BUILD_SOURCEVERSION") if verbose: click.echo(f"BUILD_SOURCEVERSION: {head_commit}\n") if head_commit: commit_list = get_list_commit_SHA("{}~1...".format(head_commit)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" " Repository URL: <Fill if public>\n" f" BUILD_SOURCEVERSION: {head_commit}")
def drone_range(verbose: bool) -> List[str]: # pragma: no cover before_sha = os.getenv("DRONE_COMMIT_BEFORE") if verbose: click.echo(f"DRONE_COMMIT_BEFORE: {before_sha}\n") if before_sha and before_sha != EMPTY_SHA: commit_list = get_list_commit_SHA("{}..".format(before_sha)) if commit_list: return commit_list raise click.ClickException( "Unable to get commit range. Please submit an issue with the following info:\n" " Repository URL: <Fill if public>\n" f" DRONE_COMMIT_BEFORE: {before_sha}")
def prepush_cmd(ctx: click.Context, prepush_args: List[str]) -> int: # pragma: no cover """ scan as a pre-push git hook. """ config = ctx.obj["config"] local_commit, remote_commit = collect_from_precommit_env() if local_commit is None or remote_commit is None: local_commit, remote_commit = collect_from_stdin() if local_commit == EMPTY_SHA: click.echo("Deletion event or nothing to scan.") return 0 if remote_commit == EMPTY_SHA: click.echo( f"New tree event. Scanning last {config.max_commits_for_hook} commits." ) before = EMPTY_TREE after = local_commit cmd_range = ( f"--max-count={config.max_commits_for_hook+1} {EMPTY_TREE} {local_commit}" ) else: before = remote_commit after = local_commit cmd_range = f"--max-count={config.max_commits_for_hook+1} {remote_commit}...{local_commit}" # noqa commit_list = get_list_commit_SHA(cmd_range) if not commit_list: click.echo("Unable to get commit range.\n" f" before: {before}\n" f" after: {after}\n" "Skipping pre-push hook\n") return 0 if len(commit_list) > config.max_commits_for_hook: click.echo( f"Too many commits. Scanning last {config.max_commits_for_hook} commits\n" ) commit_list = commit_list[-config.max_commits_for_hook:] if config.verbose: click.echo(f"Commits to scan: {len(commit_list)}") try: check_git_dir() return scan_commit_range( client=ctx.obj["client"], cache=ctx.obj["cache"], commit_list=commit_list, output_handler=ctx.obj["output_handler"], verbose=config.verbose, exclusion_regexes=ctx.obj["exclusion_regexes"], matches_ignore=config.matches_ignore, all_policies=config.all_policies, scan_id=" ".join(commit_list), mode_header=SupportedScanMode.PRE_PUSH.value, banlisted_detectors=config.banlisted_detectors, ) except Exception as error: return handle_exception(error, config.verbose)
def prereceive_cmd(ctx: click.Context, web: bool, prereceive_args: List[str]) -> int: """ scan as a pre-receive git hook. """ config = ctx.obj["config"] output_handler = ctx.obj["output_handler"] if os.getenv("GL_PROTOCOL") == "web": # We are inside GitLab web UI output_handler = GitLabWebUIOutputHandler( show_secrets=config.show_secrets) if get_breakglass_option(): click.echo( "SKIP: breakglass detected. Skipping GitGuardian pre-receive hook." ) return 0 args = sys.stdin.read().strip().split() if len(args) < 3: raise click.ClickException(f"Invalid input arguments: {args}") before, after, *_ = args commit_list = [] if after == EMPTY_SHA: click.echo("Deletion event or nothing to scan.") return 0 if before == EMPTY_SHA: before = "HEAD" commit_list = get_list_commit_SHA( f"--max-count={config.max_commits_for_hook+1} {before}...{after}") if not commit_list: before = EMPTY_TREE click.echo( f"New tree event. Scanning last {config.max_commits_for_hook} commits." ) commit_list = get_list_commit_SHA( f"--max-count={config.max_commits_for_hook+1} {EMPTY_TREE} {after}" ) else: commit_list = get_list_commit_SHA( f"--max-count={config.max_commits_for_hook+1} {before}...{after}") if not commit_list: click.echo("Unable to get commit range.\n" f" before: {before}\n" f" after: {after}\n" "Skipping pre-receive hook\n") return 0 if len(commit_list) > config.max_commits_for_hook: click.echo( f"Too many commits. Scanning last {config.max_commits_for_hook} commits\n" ) commit_list = commit_list[-config.max_commits_for_hook:] if config.verbose: click.echo(f"Commits to scan: {len(commit_list)}") try: with ExitAfter(get_prereceive_timeout()): return_code = scan_commit_range( client=ctx.obj["client"], cache=ctx.obj["cache"], commit_list=commit_list, output_handler=output_handler, verbose=config.verbose, exclusion_regexes=ctx.obj["exclusion_regexes"], matches_ignore=config.matches_ignore, all_policies=config.all_policies, scan_id=" ".join(commit_list), mode_header=SupportedScanMode.PRE_RECEIVE.value, banlisted_detectors=config.banlisted_detectors, ) if return_code: click.echo( """Rewrite your git history to delete evidence of your secrets. Use environment variables to use your secrets instead and store them in a file not tracked by git. If you don't want to go through this painful git history rewrite in the future, you can set up ggshield in your pre commit: https://docs.gitguardian.com/internal-repositories-monitoring/integrations/git_hooks/pre_commit Use it carefully: if those secrets are false positives and you still want your push to pass, run: 'git push -o breakglass'""") return return_code except TimeoutError: return 0 except Exception as error: return handle_exception(error, config.verbose)