Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(terraform): add extra handling around private GitHub Terraform modules #4699

Merged
merged 1 commit into from
Mar 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions checkov/common/goget/github/get_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import shutil

from checkov.common.goget.base_getter import BaseGetter

from checkov.common.util.contextmanagers import temp_environ

TAG_PATTERN = re.compile(r'\?(ref=)(?P<tag>(.*))')
try:
Expand Down Expand Up @@ -52,10 +52,11 @@ def do_get(self) -> str:

def _clone(self, git_url: str, clone_dir: str) -> None:
self.logger.debug(f"cloning {self.url if '@' not in self.url else self.url.split('@')[1]} to {clone_dir}")
if self.tag:
Repo.clone_from(git_url, clone_dir, depth=1, b=self.tag)
else:
Repo.clone_from(git_url, clone_dir, depth=1)
with temp_environ(GIT_TERMINAL_PROMPT="0"): # disables user prompts originating from GIT
if self.tag:
Repo.clone_from(git_url, clone_dir, depth=1, b=self.tag)
else:
Repo.clone_from(git_url, clone_dir, depth=1)

# Split source url into Git url and subdirectory path e.g. test.com/repo//repo/subpath becomes 'test.com/repo', '/repo/subpath')
# Also see reference implementation @ go-getter https://github.com/hashicorp/go-getter/blob/main/source.go
Expand Down
21 changes: 21 additions & 0 deletions checkov/common/util/contextmanagers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
from contextlib import contextmanager
from typing import Any, Generator


@contextmanager
def temp_environ(**kwargs: Any) -> Generator[None, None, None]:
"""Temporarily set environment variables and restores previous values

copy of https://gist.github.com/igniteflow/7267431?permalink_comment_id=2553451#gistcomment-2553451
"""
original_env = {key: os.getenv(key) for key in kwargs}
os.environ.update(kwargs)
try:
yield
finally:
for key, value in original_env.items():
if value is None:
del os.environ[key]
else:
os.environ[key] = value
4 changes: 4 additions & 0 deletions checkov/terraform/module_loading/loaders/git_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ def _load_module(self, module_params: ModuleParams) -> ModuleContent:
git_getter.do_get()
except Exception as e:
str_e = str(e)
if os.getenv("GITHUB_PAT") and not module_params.token and "could not read Username for" in str_e:
# we probably try to access a private repository, but a GITHUB_PAT was set,
# but the current loader (ex. GithubLoader) is not using it
return ModuleContent(dir=None, failed_url=module_params.module_source)
if 'File exists' not in str_e and 'already exists and is not an empty directory' not in str_e:
self.logger.error(f"failed to get {module_params.module_source} because of {e}")
return ModuleContent(dir=None, failed_url=module_params.module_source)
Expand Down
6 changes: 6 additions & 0 deletions github_action_resources/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ echo "BC_RUN_ID=${GITHUB_RUN_NUMBER}"
echo "BC_RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}""
echo "BC_REPOSITORY_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}""

# Overrides all GitHub URLs with the provided PAT (needed for downloading private modules from GitHub)
# This is meant to be a last resort, if our internal mechanism doesn't work
if [ -n "$GITHUB_OVERRIDE_URL" ] && [ "$GITHUB_OVERRIDE_URL" = "true" ]; then
git config --global url."https://x-access-token:${GITHUB_PAT}@github.com/".insteadOf "https://github.com/"
fi

# If Docker image is used, default to that
if [ -n "$INPUT_DOCKER_IMAGE" ]; then
DOCKER_IMAGE_FLAG="--docker-image $INPUT_DOCKER_IMAGE"
Expand Down
26 changes: 26 additions & 0 deletions tests/common/utils/test_contextmanagers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os

from checkov.common.util.contextmanagers import temp_environ


def test_temp_environ():
# given
assert os.getenv("EXAMPLE_ENV_VAR") is None

# when/then
with temp_environ(EXAMPLE_ENV_VAR="example"):
assert os.getenv("EXAMPLE_ENV_VAR") == "example"

assert os.getenv("EXAMPLE_ENV_VAR") is None


def test_temp_environ_existing_env():
# given
os.environ["EXAMPLE_ENV_VAR"] = "example"

# when/then
with temp_environ(EXAMPLE_ENV_VAR="override_example"):
assert os.getenv("EXAMPLE_ENV_VAR") == "override_example"

assert os.environ["EXAMPLE_ENV_VAR"] == "example"
del os.environ["EXAMPLE_ENV_VAR"] # cleanup