Compare commits

...

4 Commits

Author SHA1 Message Date
Ryan Petrello
c1ab815c80 Bump version to 17.1.0 2021-03-10 08:53:09 -05:00
Chris Meyers
20e77c0092 fix iso when private_data_dir is more than 1 subdir
* ISO job runs will now correctly mirror the control node
private_data_dir structure even when/if the private_data_dir is multiple
directories deep.
* The filesystem jail for bubblewrap now lives in
/tmp/bwrap_<job_id>_xxx along side private_data_dir
/tmp/bwrap_<job_id>_xxx/awx_<job_id>>_xxx This allows for the cleanup
job to remove all dirs for a job.
* Modified cleanup job to work with new /tmp/bwrap_<job_id>_xxx schema
2021-03-10 08:45:09 -05:00
Chris Meyers
de4d73d656 jailed tasks can not share files
* Permission changes in bubblewrap shared directories persist when the
jailed tasks finish execution. Effectively, this allows playbooks
executing as awx to share files with lower privileged users on the
system.
* To prevent this, we wrap the directory that we intend to share with
bubblewrap in another directory that is owned by awx with permissions
700. The wrapped directory permissions can be changed by the jailed task
while the wrapper directory can not.
* Given `/tmp/bwrap_3_abcd/awx_3_1234/` `bwrap_3_abcd` is the wrapper
directory and `awx_3_1234` is the wrapped directory.
2021-03-10 08:45:06 -05:00
Ryan Petrello
3358e568b5 resolve a permissions error related to redis
see: https://github.com/ansible/awx/issues/9401
2021-03-10 08:44:59 -05:00
9 changed files with 59 additions and 43 deletions

View File

@@ -2,6 +2,10 @@
This is a list of high-level changes for each release of AWX. A full list of commits can be found at `https://github.com/ansible/awx/releases/tag/<version>`.
# 17.1.0 (March 9th, 2021)
- Addressed a security issue in AWX (CVE-2021-20253)
- Fixed a bug permissions error related to redis in K8S-based deployments: https://github.com/ansible/awx/issues/9401
# 17.0.1 (January 26, 2021)
- Fixed pgdocker directory permissions issue with Local Docker installer: https://github.com/ansible/awx/pull/9152
- Fixed a bug in the UI which caused toggle settings to not be changed when clicked: https://github.com/ansible/awx/pull/9093

View File

@@ -1 +1 @@
17.0.1
17.1.0

View File

@@ -169,7 +169,7 @@ class IsolatedManager(object):
extravars = {
'src': self.private_data_dir,
'dest': settings.AWX_PROOT_BASE_PATH,
'dest': os.path.split(self.private_data_dir)[0],
'ident': self.ident,
'job_id': self.instance.id,
}

View File

@@ -893,10 +893,19 @@ class BaseTask(object):
'''
Create a temporary directory for job-related files.
'''
path = tempfile.mkdtemp(prefix='awx_%s_' % instance.pk, dir=settings.AWX_PROOT_BASE_PATH)
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
bwrap_path = tempfile.mkdtemp(
prefix=f'bwrap_{instance.pk}_',
dir=settings.AWX_PROOT_BASE_PATH
)
os.chmod(bwrap_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
if settings.AWX_CLEANUP_PATHS:
self.cleanup_paths.append(path)
self.cleanup_paths.append(bwrap_path)
path = tempfile.mkdtemp(
prefix='awx_%s_' % instance.pk,
dir=bwrap_path,
)
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
runner_project_folder = os.path.join(path, 'project')
if not os.path.exists(runner_project_folder):
# Ansible Runner requires that this directory exists.
@@ -989,14 +998,7 @@ class BaseTask(object):
show_paths = self.proot_show_paths + local_paths + \
settings.AWX_PROOT_SHOW_PATHS
pi_path = settings.AWX_PROOT_BASE_PATH
if not self.instance.is_isolated() and not self.instance.is_containerized:
pi_path = tempfile.mkdtemp(
prefix='ansible_runner_pi_',
dir=settings.AWX_PROOT_BASE_PATH
)
os.chmod(pi_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
self.cleanup_paths.append(pi_path)
pi_path = os.path.split(private_data_dir)[0]
process_isolation_params = {
'process_isolation': True,
@@ -1008,6 +1010,8 @@ class BaseTask(object):
'/etc/ssh',
'/var/lib/awx',
'/var/log',
'/home',
'/var/tmp',
settings.PROJECTS_ROOT,
settings.JOBOUTPUT_ROOT,
] + getattr(settings, 'AWX_PROOT_HIDE_PATHS', None) or [],

View File

@@ -552,8 +552,8 @@ class TestGenericRun():
task.should_use_proot = lambda instance: True
task.instance = job
private_data_dir = '/foo'
cwd = '/bar'
private_data_dir = os.path.join(settings.AWX_PROOT_BASE_PATH, 'foo')
cwd = '/the/bar'
settings.AWX_PROOT_HIDE_PATHS = ['/AWX_PROOT_HIDE_PATHS1', '/AWX_PROOT_HIDE_PATHS2']
settings.ANSIBLE_VENV_PATH = '/ANSIBLE_VENV_PATH'
@@ -578,7 +578,7 @@ class TestGenericRun():
'/AWX_PROOT_HIDE_PATHS1',
'/AWX_PROOT_HIDE_PATHS2']:
assert p in process_isolation_params['process_isolation_hide_paths']
assert 9 == len(process_isolation_params['process_isolation_hide_paths'])
assert 11 == len(process_isolation_params['process_isolation_hide_paths'])
assert '/ANSIBLE_VENV_PATH' in process_isolation_params['process_isolation_ro_paths']
assert '/AWX_VENV_PATH' in process_isolation_params['process_isolation_ro_paths']
assert 2 == len(process_isolation_params['process_isolation_ro_paths'])

View File

@@ -863,7 +863,7 @@ def wrap_args_with_proot(args, cwd, **kwargs):
new_args = [getattr(settings, 'AWX_PROOT_CMD', 'bwrap'), '--unshare-pid', '--dev-bind', '/', '/', '--proc', '/proc']
hide_paths = [settings.AWX_PROOT_BASE_PATH]
if not kwargs.get('isolated'):
hide_paths.extend(['/etc/tower', '/var/lib/awx', '/var/log', '/etc/ssh',
hide_paths.extend(['/etc/tower', '/var/lib/awx', '/var/log', '/etc/ssh', '/var/tmp', '/home',
settings.PROJECTS_ROOT, settings.JOBOUTPUT_ROOT])
hide_paths.extend(getattr(settings, 'AWX_PROOT_HIDE_PATHS', None) or [])
for path in sorted(set(hide_paths)):

View File

@@ -19,7 +19,6 @@ from ansible.module_utils.basic import AnsibleModule
import glob
import os
import re
import shutil
import datetime
import subprocess
@@ -38,32 +37,35 @@ def main():
# this datetime, then it will be deleted because its job has finished
job_cutoff = datetime.datetime.now() - datetime.timedelta(hours=1)
for search_pattern in [
'/tmp/awx_[0-9]*_*', '/tmp/ansible_runner_pi_*',
]:
for path in glob.iglob(search_pattern):
st = os.stat(path)
modtime = datetime.datetime.fromtimestamp(st.st_mtime)
BASE_DIR = '/tmp'
if modtime > job_cutoff:
continue
elif modtime > folder_cutoff:
bwrap_pattern = 'bwrap_[0-9]*_*'
private_data_dir_pattern = 'awx_[0-9]*_*'
bwrap_path_pattern = os.path.join(BASE_DIR, bwrap_pattern)
for bwrap_path in glob.iglob(bwrap_path_pattern):
st = os.stat(bwrap_path)
modtime = datetime.datetime.fromtimestamp(st.st_mtime)
if modtime > job_cutoff:
continue
elif modtime > folder_cutoff:
private_data_dir_path_pattern = os.path.join(BASE_DIR, bwrap_path, private_data_dir_pattern)
private_data_dir_path = next(glob.iglob(private_data_dir_path_pattern), None)
if private_data_dir_path:
try:
re_match = re.match(r'\/tmp\/awx_\d+_.+', path)
if re_match is not None:
try:
if subprocess.check_call(['ansible-runner', 'is-alive', path]) == 0:
continue
except subprocess.CalledProcessError:
# the job isn't running anymore, clean up this path
module.debug('Deleting path {} its job has completed.'.format(path))
except (ValueError, IndexError):
continue
else:
module.debug('Deleting path {} because modification date is too old.'.format(path))
changed = True
paths_removed.add(path)
shutil.rmtree(path)
if subprocess.check_call(['ansible-runner', 'is-alive', private_data_dir_path]) == 0:
continue
except subprocess.CalledProcessError:
# the job isn't running anymore, clean up this path
module.debug('Deleting path {} its job has completed.'.format(bwrap_path))
module.debug('Deleting path {} due to private_data_dir not being found.'.format(bwrap_path))
else:
module.debug('Deleting path {} because modification date is too old.'.format(bwrap_path))
changed = True
paths_removed.add(bwrap_path)
shutil.rmtree(bwrap_path)
module.exit_json(changed=changed, paths_removed=list(paths_removed))

View File

@@ -1 +1 @@
17.0.1
17.1.0

View File

@@ -362,6 +362,9 @@ spec:
- name: {{ kubernetes_deployment_name }}-redis-socket
mountPath: "/var/run/redis"
- name: {{ kubernetes_deployment_name }}-redis-data
mountPath: "/data"
resources:
requests:
memory: "{{ redis_mem_request }}Gi"
@@ -472,6 +475,9 @@ spec:
- name: {{ kubernetes_deployment_name }}-redis-socket
emptyDir: {}
- name: {{ kubernetes_deployment_name }}-redis-data
emptyDir: {}
---
apiVersion: v1
kind: Service