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

feat(utils): implement remove-unsafe-symlinks flag for cachi2 #2145

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
10 changes: 9 additions & 1 deletion atomic_reactor/plugins/cachi2_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,15 @@ def process_remote_sources(self) -> List[Dict[str, Any]]:
remote_source_data["ref"]
)

enforce_sandbox(source_path_app, remove_unsafe_symlinks=False)
remove_unsafe_symlinks = False
flags = remote_source_data.get("flags", [])
if "remove-unsafe-symlinks" in flags:
remove_unsafe_symlinks = True

enforce_sandbox(
source_path_app,
remove_unsafe_symlinks,
)
validate_paths(source_path_app, remote_source_data.get("packages", {}))

if clone_only(remote_source_data):
Expand Down
3 changes: 2 additions & 1 deletion atomic_reactor/utils/cachi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ class SymlinkSandboxError(Exception):
"""Found symlink(s) pointing outside the sandbox."""


def enforce_sandbox(repo_root: Path, remove_unsafe_symlinks: bool) -> None:
def enforce_sandbox(repo_root: Path, remove_unsafe_symlinks: bool = False) -> None:
"""
Check that there are no symlinks that try to leave the cloned repository.

:param (str | Path) repo_root: absolute path to root of cloned repository
:param bool remove_unsafe_symlinks: remove unsafe symlinks if any are found
:raises OsbsValidationException: if any symlink points outside of cloned repository
"""
for path_to_dir, subdirs, files in os.walk(repo_root):
Expand Down
31 changes: 31 additions & 0 deletions tests/plugins/test_cachi2_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
of the BSD license. See the LICENSE file for details.
"""

from pathlib import Path
from textwrap import dedent
import os.path
import json
Expand Down Expand Up @@ -35,6 +36,7 @@
from tests.mock_env import MockEnv

from tests.stubs import StubSource
from tests.utils.test_cachi2 import Symlink, write_file_tree


REMOTE_SOURCE_REPO = 'https://git.example.com/team/repo.git'
Expand Down Expand Up @@ -370,6 +372,35 @@ def test_dependency_replacements(workflow):
expect_error="Dependency replacements are not supported by Cachi2")


def test_enforce_sandbox(workflow: DockerBuildWorkflow) -> None:
"""Should remove symlink pointing outside of repository"""
container_yaml_config = dedent(f"""\
remote_source:
flags:
- remove-unsafe-symlinks
repo: {REMOTE_SOURCE_REPO}
ref: {REMOTE_SOURCE_REF}
pkg_managers: []
""")

mock_repo_config(workflow, data=container_yaml_config)

def clone_f(repo, target_dir, ref):
bad_symlink = Path(target_dir / 'symlink_to_root')
with open(target_dir / "clone.txt", "w") as f:
f.write(f"{repo}:{ref}")
f.flush()
write_file_tree({bad_symlink: Symlink("/")}, target_dir)
assert Path(target_dir / bad_symlink).exists()

mocked = flexmock(Cachi2InitPlugin)
mocked.should_receive('clone_remote_source').replace_with(clone_f)
Cachi2InitPlugin(workflow).run()

assert not Path(workflow.build_dir.path / CACHI2_BUILD_DIR / "remote-source"
/ CACHI2_BUILD_APP_DIR / "symlink_to_root").exists()


def run_plugin_with_args(workflow, dependency_replacements=None, expect_error=None,
expect_result=True, expected_plugin_results=None):
runner = (MockEnv(workflow)
Expand Down
2 changes: 1 addition & 1 deletion tests/utils/test_cachi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def test_remote_source_invalid_paths(tmpdir, remote_source_packages, expected_er


def test_remote_source_path_to_symlink_out_of_repo(tmpdir):
"""If cloned repo contains symlink that points out fo repo,
"""If cloned repo contains symlink that points out of repo,
path in packages shouldn't be allowed"""
tmpdir_path = Path(tmpdir)

Expand Down
Loading