Skip to content
This repository was archived by the owner on Mar 20, 2024. It is now read-only.

Commit 00e0efd

Browse files
committed
Rework SSH key handling and configuration
I'm running homu in OpenShift v3/Kubernetes where it's installed (as root) to `/usr`, but we run as non-root. This follows general best practice that apps shouldn't be able to mutate their code. However, we were trying to write the ssh key to `/usr`. Fix this by generating a tempfile. This is also more secure as it closes a prior race condition where we'd write the file with potentially non-private access permissions, then chmod it. Also rework things so that we only write the key once at startup. By using `NamedTemporaryFile`, it'll be `unlink()ed` once the object goes out of scope. To keep it alive long enough, pass it as an argument to the "main loop". Secondly, I want to have the github.com host key in a ConfigMap, distinct from the code. And I want to tweak the ssh configuration for https://stribika.github.io/2015/01/04/secure-secure-shell.html among other things. Hence, this also adds a `ssh_config_file` config option.
1 parent b82e98b commit 00e0efd

File tree

3 files changed

+24
-14
lines changed

3 files changed

+24
-14
lines changed

cfg.sample.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ app_client_secret = ""
2020
#ssh_key = """
2121
#"""
2222

23+
# If you're using local git, you may want to set up a ssh-config
24+
# file specific to github.com, primarily to ensure the host key
25+
# is configured.
26+
# ssh_config_path = ""
27+
2328
# By default, Homu extracts the name+email from the Github account. However,
2429
# you may want to use a private email for the account, and associate the commits
2530
# with a public email address.

homu/git_helper.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import sys
44
import os
55

6-
SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), '../cache/key')
7-
8-
96
def main():
10-
args = ['ssh', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
7+
cfgpath = os.environ.get('HOMU_SSH_CONFIG')
8+
args = ['ssh', '-i', os.getenv('HOMU_GIT_KEY_PATH'), '-S', 'none']
9+
if cfgpath is not None:
10+
args.extend(['-F', cfgpath])
11+
args.extend(sys.argv[1:])
1112
os.execvp('ssh', args)
1213

1314

homu/main.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
from queue import Queue
1616
import os
1717
import subprocess
18-
from .git_helper import SSH_KEY_FILE
1918
import shlex
19+
import tempfile
2020

2121
STATUS_TO_PRIORITY = {
2222
'success': 0,
@@ -453,12 +453,6 @@ def init_local_git_cmds(repo_cfg, git_cfg):
453453
fpath = 'cache/{}/{}'.format(repo_cfg['owner'], repo_cfg['name'])
454454
url = '[email protected]:{}/{}.git'.format(repo_cfg['owner'], repo_cfg['name'])
455455

456-
if not os.path.exists(SSH_KEY_FILE):
457-
os.makedirs(os.path.dirname(SSH_KEY_FILE), exist_ok=True)
458-
with open(SSH_KEY_FILE, 'w') as fp:
459-
fp.write(git_cfg['ssh_key'])
460-
os.chmod(SSH_KEY_FILE, 0o600)
461-
462456
if not os.path.exists(fpath):
463457
utils.logged_call(['git', 'init', fpath])
464458
utils.logged_call(['git', '-C', fpath, 'remote', 'add', 'origin', url])
@@ -488,7 +482,6 @@ def create_merge(state, repo_cfg, branch, git_cfg, ensure_merge_equal=False):
488482
desc = 'Merge conflict'
489483

490484
if git_cfg['local_git']:
491-
492485
git_cmd = init_local_git_cmds(repo_cfg, git_cfg)
493486

494487
utils.logged_call(git_cmd('fetch', 'origin', state.base_ref,
@@ -959,7 +952,8 @@ def fetch_mergeability(mergeable_que):
959952
mergeable_que.task_done()
960953

961954

962-
def check_timeout(states, queue_handler):
955+
def check_timeout(states, queue_handler, tmp_ssh_key):
956+
# This function holds a reference to tmp_ssh_key to keep it alive
963957
while True:
964958
try:
965959
for repo_label, repo_states in states.items():
@@ -1239,13 +1233,23 @@ def queue_handler():
12391233
return process_queue(states, repos, repo_cfgs, logger, buildbot_slots, db, git_cfg)
12401234

12411235
os.environ['GIT_SSH'] = os.path.join(os.path.dirname(__file__), 'git_helper.py')
1236+
sshcfg = cfg_git.get('ssh_config_path')
1237+
if sshcfg is not None:
1238+
os.environ['HOMU_SSH_CONFIG'] = sshcfg
12421239
os.environ['GIT_EDITOR'] = 'cat'
12431240

1241+
tmp_ssh_key = None
1242+
if git_cfg['local_git']:
1243+
tmp_ssh_key = tempfile.NamedTemporaryFile(prefix='homu-sshkey')
1244+
tmp_ssh_key.write(git_cfg['ssh_key'].encode('utf-8'))
1245+
tmp_ssh_key.flush()
1246+
os.environ['HOMU_GIT_KEY_PATH'] = tmp_ssh_key.name
1247+
12441248
from . import server
12451249
Thread(target=server.start, args=[cfg, states, queue_handler, repo_cfgs, repos, logger, buildbot_slots, my_username, db, repo_labels, mergeable_que, gh]).start()
12461250

12471251
Thread(target=fetch_mergeability, args=[mergeable_que]).start()
1248-
Thread(target=check_timeout, args=[states, queue_handler]).start()
1252+
Thread(target=check_timeout, args=[states, queue_handler, tmp_ssh_key]).start()
12491253

12501254
queue_handler()
12511255

0 commit comments

Comments
 (0)