community.general.tss lookup fails inside Docker (Semaphore)

Hello,

Environment:

  • Ansible Controller Host: Ubuntu / Debian

  • Automation Platform: Semaphore running inside a Docker container

  • Secret Server: On-Premise

  • Plugin: community.general.tss

I am facing a strange authentication issue with the community.general.tss (Delinea/Thycotic Secret Server) lookup plugin when running inside a Semaphore (docker rootless) environment, whereas the exact same playbook runs flawlessly when executed directly via the host’s CLI.

The Problem:

When calling the lookup plugin from within the Semaphore container, it constantly fails with:

\[ERROR\]: Task failed: Finalization of task args for 'ansible.builtin.set_fact' failed: Error while resolving value for '\_secret': The lookup plugin 'community.general.tss' failed: Secret Server lookup failure: Unable to detect server type via health check endpoints.

I have the same ansible project on my host machine. When I test my playbook, everything works fine. But it always fails when executing with Semaphore UI. Semaphore uses my Gitlab repo to execute the playbooks.

Here is my logic of “auth_tss” role:

---
- name: "[tss] Create local download directory for SSH keys"
  ansible.builtin.file:
    path: "{{ key_download_path }}"
    state: directory
    mode: "0700"
  delegate_to: localhost
  become: false
  when: inventory_hostname != 'localhost'

- name: "[tss] Fetch secret and SSH key from Secret Server"
  ansible.builtin.set_fact:
    _secret: "{{ lookup('community.general.tss', tss_secret_id,
      fetch_attachments=True,
      file_download_path=key_download_path,
      base_url=tss_base_url,
      username=tss_ansible_user,
      password=tss_ansible_pass,
      domain=tss_domain) }}"
    #_fields: "{{ _secret['items'] | items2dict(key_name='slug', value_name='itemValue') }}"
  no_log: false
  delegate_to: localhost
  become: false
  when: inventory_hostname != 'localhost'

- name: "[tss] Build field dict from secret"
  ansible.builtin.set_fact:
    _fields: "{{ _secret['items'] | items2dict(key_name='slug', value_name='itemValue') }}"
  no_log: true
  when: inventory_hostname != 'localhost'

- name: "[tss] Set restrictive permissions on SSH private key"
  ansible.builtin.file:
    path: "{{ key_download_path }}/{{ tss_secret_id }}_private-key"
    mode: "0600"
  delegate_to: localhost
  become: false
  when: inventory_hostname != 'localhost'


- name: "[tss] Set Ansible connection credentials from TSS secret"
  ansible.builtin.set_fact:
    ansible_user: "{{ _fields['username'] }}"
    ansible_become_password: "{{ _fields['password'] | default('') }}"
    ansible_ssh_private_key_file: "{{ key_download_path }}/{{ tss_secret_id }}_private-key"
    ansible_ssh_private_key_file_passphrase: "{{ _fields['private-key-passphrase'] | default('') }}"
  no_log: false
  when: inventory_hostname != 'localhost'


and here is my playbook im testing:

---
- name: Configure unattended upgrades (custom secure setup)
  hosts: ubuntu
  gather_facts: false

  pre_tasks:
    - name: TSS Authentication
      ansible.builtin.import_role:
        name: auth_tss
      tags: [always]

  roles:
    - unattended_upgrades_custom

I really don’t know what the problem is. Do I miss something? Do I need to define the variables like “tss_ansible_user” in semaphore UI or in my repo?

Any help would be appreciated!

Hi @Tydeluz ,

Are you connecting to a locally hosted Secret Server instance or Secret Server Cloud? I have more experience with the Delinea plugin for AAP/AWX but there is a bug where the logic only supports a locally hosted Secret Server instance and would fail if you tried to connect to Secret Server Cloud.

My AWX PR from 2024 is still open (although I believe RH fixed it in the latest release of AAP) and it looks like community.general.tss has the same.

I don’t have experience with Semaphore but wanted to call that out in case you were trying to use Secret Server Cloud.

Best regards,

Joe

Hi @iwt-cmd,

Thank you for your quick response.

Just to clarify: our Secret Server is hosted on-premises, so it is running locally within our environment.

Best regards,

Dennis