Reapply "Move the home directory outside of work/"
This reverts commit 279bbfb346.
Change-Id: If734440ca26c9deca9070dc480661eab79390c63
This commit is contained in:
@@ -32,6 +32,11 @@ that is readable and writable by the job. The hierarchy is:
|
||||
Where the Ansible log for the job is written; your job
|
||||
may place other logs here as well.
|
||||
|
||||
The home directory of the user running the job is outside this
|
||||
hierarchy. A future version of Zuul will restrict which files in the
|
||||
home directory may be carried over between playbooks. To use files in
|
||||
later playbooks, put them under ``work/`` rather than ``$HOME``.
|
||||
|
||||
Git Repositories
|
||||
----------------
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- name: Test skopeo inside the executor bwrap
|
||||
command: docker run --rm -i --privileged quay.io/zuul-ci/zuul-executor:latest zuul-bwrap /tmp skopeo copy docker://quay.io/zuul-ci/zuul:latest oci:test
|
||||
command: docker run --rm -i --privileged quay.io/zuul-ci/zuul-executor:latest zuul-bwrap /tmp /tmp skopeo copy docker://quay.io/zuul-ci/zuul:latest oci:test
|
||||
register: skopeo_output
|
||||
- name: Verify that skopeo ran correctly
|
||||
assert:
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The home directory of the user that is used to run playbooks on
|
||||
the executor has been moved outside of the build's ``work/``
|
||||
directory. A future version of Zuul will restict which files in
|
||||
the home directory may be carried over between playbooks. Files
|
||||
that should persist between playbooks should generally be placed
|
||||
in the build`s ``work/`` directory instead.
|
||||
@@ -38,10 +38,12 @@ class TestBubblewrap(testtools.TestCase):
|
||||
bwrap.check()
|
||||
context = bwrap.getExecutionContext()
|
||||
work_dir = tempfile.mkdtemp()
|
||||
home_dir = tempfile.mkdtemp()
|
||||
ssh_agent = SshAgent()
|
||||
self.addCleanup(ssh_agent.stop)
|
||||
ssh_agent.start()
|
||||
po = context.getPopen(work_dir=work_dir,
|
||||
home_dir=home_dir,
|
||||
ssh_auth_sock=ssh_agent.env['SSH_AUTH_SOCK'])
|
||||
self.assertTrue(po.fds[0] > 2)
|
||||
self.assertTrue(po.fds[1] > 2)
|
||||
@@ -68,10 +70,12 @@ class TestBubblewrap(testtools.TestCase):
|
||||
bwrap.check()
|
||||
context = bwrap.getExecutionContext()
|
||||
work_dir = tempfile.mkdtemp()
|
||||
home_dir = tempfile.mkdtemp()
|
||||
ssh_agent = SshAgent()
|
||||
self.addCleanup(ssh_agent.stop)
|
||||
ssh_agent.start()
|
||||
po = context.getPopen(work_dir=work_dir,
|
||||
home_dir=home_dir,
|
||||
ssh_auth_sock=ssh_agent.env['SSH_AUTH_SOCK'])
|
||||
self.assertTrue(po.fds[0] > 2)
|
||||
self.assertTrue(po.fds[1] > 2)
|
||||
@@ -93,11 +97,13 @@ class TestBubblewrap(testtools.TestCase):
|
||||
bwrap.check()
|
||||
context = bwrap.getExecutionContext()
|
||||
work_dir = tempfile.mkdtemp()
|
||||
home_dir = tempfile.mkdtemp()
|
||||
ansible_dir = tempfile.mkdtemp()
|
||||
ssh_agent = SshAgent()
|
||||
self.addCleanup(ssh_agent.stop)
|
||||
ssh_agent.start()
|
||||
po = context.getPopen(work_dir=work_dir,
|
||||
home_dir=home_dir,
|
||||
ansible_dir=ansible_dir,
|
||||
ssh_auth_sock=ssh_agent.env['SSH_AUTH_SOCK'])
|
||||
leak_time = 60
|
||||
|
||||
@@ -251,8 +251,8 @@ class BubblewrapExecutionContext(BaseExecutionContext):
|
||||
# Need users and groups
|
||||
uid = os.getuid()
|
||||
passwd = list(pwd.getpwuid(uid))
|
||||
# Replace our user's actual home directory with the work dir.
|
||||
passwd = passwd[:5] + [kwargs['work_dir']] + passwd[6:]
|
||||
# Replace our user's actual home directory with the build home dir.
|
||||
passwd = passwd[:5] + [kwargs['home_dir']] + passwd[6:]
|
||||
passwd_bytes = b':'.join(
|
||||
['{}'.format(x).encode('utf8') for x in passwd])
|
||||
(passwd_r, passwd_w) = os.pipe()
|
||||
@@ -331,7 +331,8 @@ class BubblewrapDriver(Driver, WrapperInterface):
|
||||
# Validate basic bwrap functionality before we attempt to run
|
||||
# workloads under bwrap.
|
||||
context = self.getExecutionContext()
|
||||
popen = context.getPopen(work_dir='/tmp')
|
||||
popen = context.getPopen(work_dir='/tmp',
|
||||
home_dir='/tmp')
|
||||
p = popen(['id'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
p.communicate()
|
||||
@@ -340,7 +341,7 @@ class BubblewrapDriver(Driver, WrapperInterface):
|
||||
" ".join(shlex.quote(c)
|
||||
for c in popen.command + ['id']))
|
||||
raise Exception('bwrap execution validation failed. You can '
|
||||
'use `zuul-bwrap /tmp id` to investigate '
|
||||
'use `zuul-bwrap /tmp /tmp id` to investigate '
|
||||
'manually.')
|
||||
|
||||
def setCgroupManager(self, cgroup_manager):
|
||||
@@ -424,6 +425,7 @@ class BubblewrapDriver(Driver, WrapperInterface):
|
||||
'--ro-bind', '/etc/localtime', '/etc/localtime',
|
||||
'--bind', '{work_dir}', '{work_dir}',
|
||||
'--tmpfs', '{work_dir}/tmp',
|
||||
'--bind', '{home_dir}', '{home_dir}',
|
||||
'--proc', '/proc',
|
||||
'--dev', '/dev',
|
||||
'--chdir', '{work_dir}',
|
||||
@@ -476,6 +478,7 @@ def main(args=None):
|
||||
parser.add_argument('--rw-paths', nargs='+')
|
||||
parser.add_argument('--secret', nargs='+')
|
||||
parser.add_argument('work_dir')
|
||||
parser.add_argument('home_dir')
|
||||
parser.add_argument('run_args', nargs='+')
|
||||
cli_args = parser.parse_args()
|
||||
|
||||
@@ -494,6 +497,7 @@ def main(args=None):
|
||||
secrets)
|
||||
|
||||
popen = context.getPopen(work_dir=cli_args.work_dir,
|
||||
home_dir=cli_args.home_dir,
|
||||
ssh_auth_sock=ssh_auth_sock)
|
||||
x = popen(cli_args.run_args)
|
||||
x.wait()
|
||||
|
||||
+20
-15
@@ -647,11 +647,12 @@ class JobDir(object):
|
||||
# project_0
|
||||
# <git.example.com>
|
||||
# <project>
|
||||
# home (mounted in bwrap read-write)
|
||||
# .ssh
|
||||
# known_hosts
|
||||
# kube (mounted in bwrap read-only)
|
||||
# config
|
||||
# work (mounted in bwrap read-write)
|
||||
# .ssh
|
||||
# known_hosts
|
||||
# src
|
||||
# <git.example.com>
|
||||
# <project>
|
||||
@@ -666,6 +667,13 @@ class JobDir(object):
|
||||
tmpdir = tempfile.gettempdir()
|
||||
self.root = os.path.realpath(os.path.join(tmpdir, build_uuid))
|
||||
os.mkdir(self.root, 0o700)
|
||||
self.home = os.path.join(self.root, 'home')
|
||||
os.makedirs(self.home)
|
||||
ssh_dir = os.path.join(self.home, '.ssh')
|
||||
os.mkdir(ssh_dir, 0o700)
|
||||
# A home directory with nothing in it for utility calls.
|
||||
self.utility_home = os.path.join(self.root, 'utility-home')
|
||||
os.makedirs(self.utility_home)
|
||||
self.work_root = os.path.join(self.root, 'work')
|
||||
os.makedirs(self.work_root)
|
||||
self.src_root = os.path.join(self.work_root, 'src')
|
||||
@@ -689,8 +697,6 @@ class JobDir(object):
|
||||
os.makedirs(self.trusted_root)
|
||||
self.untrusted_root = os.path.join(self.root, 'untrusted')
|
||||
os.makedirs(self.untrusted_root)
|
||||
ssh_dir = os.path.join(self.work_root, '.ssh')
|
||||
os.mkdir(ssh_dir, 0o700)
|
||||
self.kube_dir = os.path.join(self.root, "kube")
|
||||
os.makedirs(self.kube_dir)
|
||||
self.kubeconfig = os.path.join(self.kube_dir, "config")
|
||||
@@ -745,11 +751,11 @@ class JobDir(object):
|
||||
with _safe_open(self.result_data_file, 'w'):
|
||||
pass
|
||||
self.known_hosts = os.path.join(ssh_dir, 'known_hosts')
|
||||
# This file is not created or used by Zuul, but we forbid its
|
||||
# use in jobs.
|
||||
# The ssh config file is not created or used by Zuul, but we
|
||||
# forbid its use in jobs.
|
||||
self.path_blocklist = [
|
||||
os.path.join(self.work_root, '.ssh', 'config'),
|
||||
os.path.join(self.work_root, '.kube', 'config'),
|
||||
os.path.join(self.home, '.ssh', 'config'),
|
||||
os.path.join(self.home, '.kube', 'config'),
|
||||
]
|
||||
self.inventory = os.path.join(self.ansible_root, 'inventory.yaml')
|
||||
self.logging_json = os.path.join(self.ansible_root, 'logging.json')
|
||||
@@ -1993,7 +1999,7 @@ class AnsibleJob(object):
|
||||
# the work directory.
|
||||
env_copy = {}
|
||||
env_copy['TMP'] = self.jobdir.local_tmp
|
||||
env_copy['HOME'] = self.jobdir.work_root
|
||||
env_copy['HOME'] = self.jobdir.utility_home
|
||||
ro_paths = []
|
||||
rw_paths = []
|
||||
secrets = {}
|
||||
@@ -2001,6 +2007,7 @@ class AnsibleJob(object):
|
||||
context = wrapper.getExecutionContext(ro_paths, rw_paths, secrets)
|
||||
return env_copy, context.getPopen(
|
||||
work_dir=self.jobdir.work_root,
|
||||
home_dir=self.jobdir.utility_home,
|
||||
share_net=False,
|
||||
)
|
||||
|
||||
@@ -3395,9 +3402,8 @@ class AnsibleJob(object):
|
||||
allow_pre_fail, wrapped=True, cleanup=False,
|
||||
phase=None, index=None):
|
||||
# Cleanup any forbidden files in the home directory.
|
||||
# TODO: move the home directory to a subdir of work/ and add a
|
||||
# job-based allowlist of files to explicitly copy between
|
||||
# playbook runs.
|
||||
# TODO: add a job-based allowlist of files to explicitly copy
|
||||
# between playbook runs.
|
||||
|
||||
for path in self.jobdir.path_blocklist:
|
||||
try:
|
||||
@@ -3471,12 +3477,11 @@ class AnsibleJob(object):
|
||||
|
||||
popen = context.getPopen(
|
||||
work_dir=self.jobdir.work_root,
|
||||
home_dir=self.jobdir.home,
|
||||
ssh_auth_sock=env_copy.get('SSH_AUTH_SOCK'))
|
||||
|
||||
env_copy['ANSIBLE_CONFIG'] = config_file
|
||||
# NOTE(pabelanger): Default HOME variable to jobdir.work_root, as it is
|
||||
# possible we don't bind mount current zuul user home directory.
|
||||
env_copy['HOME'] = self.jobdir.work_root
|
||||
env_copy['HOME'] = self.jobdir.home
|
||||
|
||||
with self.proc_lock:
|
||||
self.proc_cleanup = playbook.cleanup
|
||||
|
||||
Reference in New Issue
Block a user