mirror of https://github.com/ansible/ansible.git
* Fix installing roles containing symlinks
Fix sanitizing tarfile symlinks relative to the link directory instead of the archive
For example:
role
├── handlers
│ └── utils.yml -> ../tasks/utils/suite.yml
The link ../tasks/utils/suite.yml will resolve to a path outside of the link's directory, but within the role
role/handlers/../tasks/utils/suite.yml
the resolved path relative to the role is tasks/utils/suite.yml, but if the symlink is set to that value, tarfile would extract it from role/handlers/tasks/utils/suite.yml
* Replace overly forgiving test case with tests for a symlink in a subdirectory of the archive and a symlink in the archive dir when these are not equivalent.
* Build test case from role files to make it easier to add test cases
Fixes #82702
Fixes #81965
Fixes #82051
(cherry picked from commit e84240db84
)
pull/83228/head
parent
04e6c51445
commit
6fe3b64990
@ -1,2 +1,3 @@
|
||||
bugfixes:
|
||||
- ansible-galaxy role install - normalize tarfile paths and symlinks using ``ansible.utils.path.unfrackpath`` and consider them valid as long as the realpath is in the tarfile's role directory (https://github.com/ansible/ansible/issues/81965).
|
||||
- ansible-galaxy role install - fix symlinks (https://github.com/ansible/ansible/issues/82702, https://github.com/ansible/ansible/issues/81965).
|
||||
|
@ -0,0 +1 @@
|
||||
common_vars/subdir/group0/main.yml
|
@ -0,0 +1 @@
|
||||
../tasks/utils/suite.yml
|
@ -1,78 +1,38 @@
|
||||
- name: create test directories
|
||||
file:
|
||||
path: '{{ remote_tmp_dir }}/dir-traversal/{{ item }}'
|
||||
state: directory
|
||||
loop:
|
||||
- source
|
||||
- target
|
||||
- roles
|
||||
|
||||
- name: create subdir in the role content to test relative symlinks
|
||||
file:
|
||||
dest: '{{ remote_tmp_dir }}/dir-traversal/source/role_subdir'
|
||||
state: directory
|
||||
|
||||
- copy:
|
||||
dest: '{{ remote_tmp_dir }}/dir-traversal/source/role_subdir/.keep'
|
||||
content: ''
|
||||
|
||||
- set_fact:
|
||||
installed_roles: "{{ remote_tmp_dir | realpath }}/dir-traversal/roles"
|
||||
|
||||
- name: build role with symlink to a directory in the role
|
||||
script:
|
||||
chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
|
||||
cmd: create-role-archive.py safe-link-dir.tar ./ role_subdir/..
|
||||
executable: '{{ ansible_playbook_python }}'
|
||||
|
||||
- name: install role successfully
|
||||
command:
|
||||
cmd: 'ansible-galaxy role install --roles-path {{ remote_tmp_dir }}/dir-traversal/roles safe-link-dir.tar'
|
||||
chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
|
||||
register: galaxy_install_ok
|
||||
|
||||
- name: check for the directory symlink in the role
|
||||
stat:
|
||||
path: "{{ installed_roles }}/safe-link-dir.tar/symlink"
|
||||
register: symlink_in_role
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- symlink_in_role.stat.exists
|
||||
- symlink_in_role.stat.lnk_source == installed_roles + '/safe-link-dir.tar'
|
||||
|
||||
- name: remove tarfile for next test
|
||||
file:
|
||||
path: '{{ remote_tmp_dir }}/dir-traversal/source/safe-link-dir.tar'
|
||||
state: absent
|
||||
|
||||
- name: build role with safe relative symlink
|
||||
script:
|
||||
chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
|
||||
cmd: create-role-archive.py safe.tar ./ role_subdir/../context.txt
|
||||
executable: '{{ ansible_playbook_python }}'
|
||||
|
||||
- name: install role successfully
|
||||
command:
|
||||
cmd: 'ansible-galaxy role install --roles-path {{ remote_tmp_dir }}/dir-traversal/roles safe.tar'
|
||||
chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
|
||||
register: galaxy_install_ok
|
||||
|
||||
- name: check for symlink in role
|
||||
stat:
|
||||
path: "{{ installed_roles }}/safe.tar/symlink"
|
||||
register: symlink_in_role
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- symlink_in_role.stat.exists
|
||||
- symlink_in_role.stat.lnk_source == installed_roles + '/safe.tar/context.txt'
|
||||
|
||||
- name: remove test directories
|
||||
file:
|
||||
path: '{{ remote_tmp_dir }}/dir-traversal/{{ item }}'
|
||||
state: absent
|
||||
loop:
|
||||
- source
|
||||
- target
|
||||
- roles
|
||||
- delegate_to: localhost
|
||||
block:
|
||||
- name: Create archive
|
||||
command: "tar -cf safe-symlinks.tar {{ role_path }}/files/safe-symlinks"
|
||||
args:
|
||||
chdir: "{{ remote_tmp_dir }}"
|
||||
|
||||
- name: Install role successfully
|
||||
command: ansible-galaxy role install --roles-path '{{ remote_tmp_dir }}/roles' safe-symlinks.tar
|
||||
args:
|
||||
chdir: "{{ remote_tmp_dir }}"
|
||||
|
||||
- name: Validate each of the symlinks exists
|
||||
stat:
|
||||
path: "{{ remote_tmp_dir }}/roles/safe-symlinks.tar/{{ item }}"
|
||||
loop:
|
||||
- defaults/main.yml
|
||||
- handlers/utils.yml
|
||||
register: symlink_stat
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- symlink_stat.results[0].stat.exists
|
||||
- symlink_stat.results[0].stat.lnk_source == ((dest, 'roles/safe-symlinks.tar/defaults/common_vars/subdir/group0/main.yml') | path_join)
|
||||
- symlink_stat.results[1].stat.exists
|
||||
- symlink_stat.results[1].stat.lnk_source == ((dest, 'roles/safe-symlinks.tar/tasks/utils/suite.yml') | path_join)
|
||||
vars:
|
||||
dest: "{{ remote_tmp_dir | realpath }}"
|
||||
|
||||
always:
|
||||
- name: Clean up
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
delegate_to: localhost
|
||||
loop:
|
||||
- "{{ remote_tmp_dir }}/roles/"
|
||||
- "{{ remote_tmp_dir }}/safe-symlinks.tar"
|
||||
|
Loading…
Reference in New Issue