--- - name: Reach Portainer via SSH tunnel through bdc hosts: localhost connection: local gather_facts: false vars: bastion_host: bdc.cci17.fr bastion_port: 17100 bastion_user: ansible portainer_ip: 10.30.0.151 portainer_port: 9443 local_port: "{{ 20000 + (9999 | random) }}" ssh_control_socket: "/tmp/ssh-tunnel-{{ local_port }}.sock" tasks: - block: - name: Open SSH tunnel (local -> portainer via bastion) shell: > ssh -p {{ bastion_port }} -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ServerAliveInterval=10 -o ServerAliveCountMax=3 -M -S {{ ssh_control_socket }} -f -N -L 127.0.0.1:{{ local_port }}:{{ portainer_ip }}:{{ portainer_port }} {{ bastion_user }}@{{ bastion_host }} changed_when: true - name: Wait for local tunnel port wait_for: host: 127.0.0.1 port: "{{ local_port }}" timeout: 20 - name: HTTPS check Portainer through tunnel uri: url: "https://127.0.0.1:{{ local_port }}/" method: GET validate_certs: false status_code: [200, 301, 302, 403] register: portainer_check - name: OK debug: msg: "✅ Portainer joignable via tunnel (status {{ portainer_check.status }})" always: - name: Close tunnel if opened shell: > test -S {{ ssh_control_socket }} && ssh -p {{ bastion_port }} -S {{ ssh_control_socket }} -O exit {{ bastion_user }}@{{ bastion_host }} || true ignore_errors: true