Skip to content

Commit 312041c

Browse files
committed
restrict the user git
1 parent f9727de commit 312041c

File tree

8 files changed

+77
-17
lines changed

8 files changed

+77
-17
lines changed

.github/workflows/system.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Install the project
2020
run: uv sync
2121
- name: Clone
22-
run: uv run commit0 clone simpy
22+
run: uv run commit0 setup simpy
2323
- name: Setup
2424
run: uv run commit0 build simpy
2525
- name: Get tests

commit0/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def main() -> None:
3030
# after hydra gets all configs, put command-line arguments back
3131
sys.argv = sys_argv
3232
# repo_split: split from command line has a higher priority than split in hydra
33-
if command in ["clone", "build", "evaluate", "evaluate-reference", "save"]:
33+
if command in ["setup", "build", "evaluate", "evaluate-reference", "save"]:
3434
if len(sys.argv) >= 3:
3535
if sys.argv[2] not in SPLIT:
3636
raise ValueError(
@@ -39,7 +39,7 @@ def main() -> None:
3939
config.repo_split = sys.argv[2]
4040
config.base_dir = os.path.abspath(config.base_dir)
4141

42-
if command == "clone":
42+
if command == "setup":
4343
commit0.harness.setup.main(
4444
config.dataset_name,
4545
config.dataset_split,

commit0/harness/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class RepoInstance(TypedDict):
2727

2828
# available commands
2929
COMMANDS = [
30-
"clone",
30+
"setup",
3131
"build",
3232
"test",
3333
"test-reference",

commit0/harness/docker_utils.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import threading
99
import time
1010
import traceback
11+
import pwd
1112
from pathlib import Path
1213
from io import BytesIO
1314
from typing import Optional, List, Union
@@ -158,23 +159,26 @@ def copy_ssh_pubkey_from_container(container: Container) -> None:
158159
if exit_code != 0:
159160
raise Exception(f"Error reading file: {output.decode('utf-8').strip()}")
160161
public_key = output.decode("utf-8").strip()
162+
public_key = f"no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {public_key}"
161163

162-
local_authorized_keys_path = os.path.expanduser("~/.ssh/authorized_keys")
163-
os.makedirs(os.path.dirname(local_authorized_keys_path), exist_ok=True)
164-
if not os.path.exists(local_authorized_keys_path):
164+
user_info = pwd.getpwnam('git')
165+
home_directory = user_info.pw_dir
166+
authorized_keys_path = os.path.join(home_directory, '.ssh', 'authorized_keys')
167+
os.makedirs(os.path.dirname(authorized_keys_path), exist_ok=True)
168+
if not os.path.exists(authorized_keys_path):
165169
# Since the file does not exist, create it
166-
open(local_authorized_keys_path, "a").close()
170+
open(authorized_keys_path, "a").close()
167171
write = True
168172
else:
169-
with open(local_authorized_keys_path, "r") as authorized_keys_file:
173+
with open(authorized_keys_path, "r") as authorized_keys_file:
170174
content = authorized_keys_file.read()
171175
if public_key not in content:
172176
write = True
173177
else:
174178
write = False
175179

176180
if write:
177-
with open(local_authorized_keys_path, "a") as authorized_keys_file:
181+
with open(authorized_keys_path, "a") as authorized_keys_file:
178182
authorized_keys_file.write(public_key + "\n")
179183

180184
except docker.errors.APIError as e:

commit0/harness/run_pytest_ids.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
extract_test_output,
1616
get_hash_string,
1717
get_ip,
18-
get_user,
1918
)
2019
from commit0.harness.execution_context import (
2120
Docker,
@@ -74,7 +73,6 @@ def main(
7473
commit_id=commit_id,
7574
test_ids=test_ids,
7675
ip=get_ip(backend),
77-
user=get_user(),
7876
)
7977
eval_file = Path(log_dir / "eval.sh")
8078
eval_file.write_text(eval_script)

commit0/harness/setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from datasets import load_dataset
55

66
from typing import Iterator
7-
from commit0.harness.utils import clone_repo, create_branch
7+
from commit0.harness.utils import clone_repo, create_branch, setup_git, add_safe_directory
88
from commit0.harness.constants import RepoInstance, SPLIT
99

1010

@@ -18,6 +18,7 @@ def main(
1818
dataset_name: str, dataset_split: str, repo_split: str, base_dir: str, branch: str
1919
) -> None:
2020
dataset: Iterator[RepoInstance] = load_dataset(dataset_name, split=dataset_split) # type: ignore
21+
setup_git(logger)
2122
for example in dataset:
2223
repo_name = example["repo"].split("/")[-1]
2324
if repo_split != "all" and repo_name not in SPLIT[repo_split]:
@@ -26,6 +27,7 @@ def main(
2627
clone_dir = os.path.abspath(os.path.join(base_dir, repo_name))
2728
local_repo = clone_repo(clone_url, clone_dir, example["base_commit"], logger)
2829
create_branch(local_repo, branch, logger)
30+
add_safe_directory(clone_dir, logger)
2931

3032

3133
__all__ = []

commit0/harness/spec.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def make_eval_script_list(instance: RepoInstance, repo_directory: str) -> list[s
152152
"ssh-keyscan {ip} >> ~/.ssh/known_hosts",
153153
f"cd {repo_directory}",
154154
"source .venv/bin/activate",
155-
f"git remote add {origin_name} ssh://{{user}}@{{ip}}:{{local_repo}}",
155+
f"git remote add {origin_name} ssh://git@{{ip}}:{{local_repo}}",
156156
f"git fetch {origin_name}",
157157
"git checkout {commit_id}",
158158
"git status",

commit0/harness/utils.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
import os
88
import time
99
import requests
10-
from typing import Optional
10+
import subprocess
11+
from typing import Optional, Tuple
1112

1213
from fastcore.net import HTTP404NotFoundError, HTTP403ForbiddenError # type: ignore
1314
from ghapi.core import GhApi
@@ -58,8 +59,63 @@ def get_ip(backend: str) -> str:
5859
return ip
5960

6061

61-
def get_user() -> str:
62-
return getpass.getuser()
62+
def run_command(command: str) -> Tuple[str, str, int]:
63+
"""
64+
Runs a shell command and returns the output, error message, and exit code.
65+
"""
66+
try:
67+
result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
68+
return result.stdout.decode('utf-8'), result.stderr.decode('utf-8'), result.returncode
69+
except subprocess.CalledProcessError as e:
70+
return e.stdout.decode('utf-8'), e.stderr.decode('utf-8'), e.returncode
71+
72+
73+
def handle_command(command: str, description: str, logger: logging.Logger) -> None:
74+
"""
75+
Runs a command and handles success or failure with appropriate messages.
76+
"""
77+
stdout, stderr, exit_code = run_command(command)
78+
if exit_code != 0:
79+
logger.error(f"Error running '{command}' which {description}:\n{stderr}")
80+
else:
81+
logger.info(f"Succeeded in running '{command}' which {description}")
82+
83+
84+
def setup_git(logger: logging.Logger) -> None:
85+
"""
86+
Sets up the 'git' user with appropriate shell settings, .ssh directory, and git-shell as login shell.
87+
"""
88+
commands = [("sudo adduser --disabled-password --gecos \"\" git", "adds git user"), ("sudo -u git bash -c 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'", "sets up .ssh directory for git"), ("cat /etc/shells", "views available shells"), ("sudo which git-shell >> /etc/shells", "adds git-shell to /etc/shells"), ("sudo chsh git -s $(which git-shell)", "changes shell for git user to git-shell")]
89+
90+
for command, description in commands:
91+
handle_command(command, description, logger)
92+
93+
94+
def is_safe_directory_added(safe_directory: str) -> bool:
95+
# Run command to get all safe directories
96+
command = "git config --system --get-all safe.directory"
97+
stdout, stderr, exit_code = run_command(command)
98+
99+
# Check if the directory is listed
100+
if exit_code == 0 and safe_directory in stdout.splitlines():
101+
return True
102+
else:
103+
return False
104+
105+
def add_safe_directory(safe_directory: str, logger: logging.Logger):
106+
safe_directory = os.path.join(safe_directory, '.git')
107+
# Check if the directory is already added
108+
if not is_safe_directory_added(safe_directory):
109+
# Command to add the directory to safe.directory
110+
command = f"git config --system --add safe.directory {safe_directory}"
111+
stdout, stderr, exit_code = run_command(command)
112+
113+
if exit_code == 0:
114+
logger.info(f"Directory '{safe_directory}' added to safe.directory.")
115+
else:
116+
logger.error(f"Error adding directory: {stderr}")
117+
else:
118+
logger.info(f"Directory '{safe_directory}' is already in the list.")
63119

64120

65121
def get_hash_string(input_string: str) -> str:

0 commit comments

Comments
 (0)