AWX 23.8.1 : getting error "Invalid linkname for tarfile member"

Getting Invalid linkname for tarfile member while running a shared role job.
Hello Community,

We are using shared role concept to run the jobs in AWX and we are getting a below error while synching the project. The project has many roles and it is getting failed on this particular role.


PLAY [Update source tree if necessary] *****************************************

TASK [Delete project directory before update] **********************************
changed: [localhost]

TASK [Update project using git] ************************************************
changed: [localhost]

TASK [Set the git repository version] ******************************************
ok: [localhost]

TASK [Repository Version] ******************************************************
ok: [localhost] => {
    "msg": "Repository Version XXXX
}

PLAY [Perform project signature/checksum verification] *************************

PLAY [Install content with ansible-galaxy command if necessary] ****************

TASK [Warn about disabled content sync] ****************************************
skipping: [localhost]

TASK [End play due to disabled content sync] ***********************************
skipping: [localhost]

TASK [Fetch galaxy roles from roles/requirements.(yml/yaml)] *******************
Username for 'https://$encrypted$: Password for 'https://$encrypted$@gitlab.com': 
Username for 'https://$encrypted$: Password for 'https://$encrypted$@gitlab.com': 
Username for 'https://$encrypted$: Password for 'https://$encrypted$@gitlab.com': 
Username for 'https://$encrypted$: Password for 'https://$encrypted$@gitlab.com': 
Username for 'https://$encrypted$: Password for 'https://$encrypted$@gitlab.com': 
failed: [localhost] (item=/var/lib/awx/projects/_9__ansible_shared_role/roles/requirements.yml)
 => {"ansible_loop_var": "item", "changed": true, "cmd": ["ansible-galaxy", "role", "install", "-r", "/var/lib/awx/projects/_9__ansible_shared_role/roles/requirements.yml"], 
"delta": "0:00:33.978908", "end": "2024-06-07 13:26:28.845210", "item": "/var/lib/awx/projects/_9__ansible_shared_role/roles/requirements.yml", "msg": "non-zero return code","rc": 1, "start": "2024-06-07 13:25:54.866302", 
"stderr": "[WARNING]: - xxxx.ansible_ldap1 was NOT installed successfully: Invalid\\nlinkname for tarfile member: 
path /etc/alternatives/mta-pam is not a subpath of\\nthe role /var/lib/awx/projects/_9__ansible_shared_role/xxxx.ansible_ldap1\\nERROR! - 
you can use --ignore-errors to skip failed roles and finish processing the list.", "stderr_lines": ["[WARNING]: - xxxx.ansible_ldap1 was NOT installed successfully: 
Invalid", "linkname for tarfile member: path /etc/alternatives/mta-pam is not a subpath of", "the role /var/lib/awx/projects/_9__ansible_shared_role/xxxx.ansible_ldap1", 
"ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list."], "stdout": "Starting galaxy role install process\\n- extracting xxxx.ansible-zabbix 
to /var/lib/awx/projects/.__awx_cache/_9__ansible_shared_role/stage/requirements_roles/xxxx.ansible-zabbix\\n- xxxx.ansible-zabbix (noprod) was installed successfully\\n- extracting xxxx.ansible_sudo 
to /var/lib/awx/projects/.__awx_cache/_9__ansible_shared_role/stage/requirements_roles/xxxx.ansible_sudo\\n- xxxx.ansible_sudo (v1.0.1) was installed successfully\\n- extracting xxxx.ansible_cdprinfo 
to /var/lib/awx/projects/.__awx_cache/_9__ansible_shared_role/stage/requirements_roles/xxxx.ansible_cdprinfo\\n- xxxx.ansible_cdprinfo was installed successfully\\n- extracting xxxx.ansible_gemsource 
to /var/lib/awx/projects/.__awx_cache/_9__ansible_shared_role/stage/requirements_roles/xxxx.ansible_gemsource\\n- xxxx.ansible_gemsource was installed successfully\\n- extracting xxxx.ansible_logarchiving 
to /var/lib/awx/projects/.__awx_cache/]}

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0   

Can you please help us to fix this issue ?

Thanks and regards
Saravana Selvaraj

Hi Saravana,

As it’s been over a year since this question was posed, you probably already figured out the solution/discovered a workaround, but I wanted to provide the solution in case you or others come across this issue in the future.

The issue you’re running into here is that, as the error implies, an invalid linkname is detected when ansible-galaxy is unpacking your role for use in your project. This was caused by a symlink in your role which is pointed at /etc/alternatives/mta-pam. Since the path that the symlink is pointed to is not a sub-path of your root role directory, Ansible is throwing an error.

There are many ways to approach this but here are a few:

  • Including the dependent file in {{ role_path }}/files/
  • Using a hard-link
  • Setting up a pre-commit hook to have git resolve the sym-link to raw file contents

Or if you ever run into this issue with something like {{ role_path }}/.ansible after running ansible-lint ., you can always add the sym-link to .gitignore and avoid having to deal with it at all (if the file is not necessary for upstream).

Why This Happens (Technical)

When AWX (or AAP) initializes a project-sync, it leverages the ansible-galaxy cli in the background to iterate over your requirements files (roles/requirements.yml, collections/requirements.yml, requirements.yml) to gather what resources must be included in the execution environment. In your case, the roles/requirements that you’ve included in your debug are from git scm sources, more specifically, gathering from Gitlab repositories.

In the backend, ansible-galaxy clones your remote repo, and then stores it in a .tar archive so that all requirements go through the same processing before inclusion down the line, whether your source is an scm, tar archive, etc.

Since your repo contents are stored in a .tar archive in the backend, ansible-galaxy then goes through the process of unpacking the files and ensuring that everything inside of the role is valid, both from a structural and security perspective. This is where your issue arises. Here in the ansible-core source code, galaxy is extracting files from the tar archive and, while doing so, removing “any relative path bits that might be in the file for security purposes”. This means that for any symbolic links contained in the archive, they are being resolved to their full path. After this is done, a check is done with if not is_subpath(full_path, resolved_archive, real=True): to ensure that the absolute path of each file resolves to one that is under the root directory of your role (your exact error message is here). Your role is failing to be synced because you have a symbolic link to /etc/alternatives/mta-pam which is not a sub-path of /var/lib/awx/projects/_9__ansible_shared_role/xxxx.ansible_ldap1.

I hope this helps you or anybody else that comes across this thread. If there’s anything you’d like me to provide some more clarification on, please let me know. If anything I said was inaccurate, please provide clarification for others below.


Thanks,
Ethan