Can't configure the location of `pyinfra-sudo-askpass-XXXXXXX` file, sudo failing in environments with restricted /tmp script execution
See original GitHub issueDescribe the bug
When running a task with _sudo=True, _ask_sudo_password=<password>
in restricted environments where script execution from /tmp
is prohibited, sudo password prompt appears. Setting config.TEMP_DIR
in an attempt to place the file in other directory does not affect this behavior.
Related to #852
To Reproduce
server.shell(f'cd {tmp_dest} && docker-compose up -d', _sudo=True, _use_sudo_password=host.data._use_sudo_password)
In my particular case, this happens on a Synology NAS with DSM 7. There is only a single reference to this restriction in the entire Internet (https://community.synology.com/enu/forum/1/post/153704), and I have yet to find how to configure that. Nevertheless, this would happen on hosts with noexec
tmp mounts, so probably worth checking this out.
Expected behavior
Being able to configure the location of the password script with TEMP_DIR
config value or a new config value (like ASK_SUDO_PASSWORD_EXE_LOCATION
)
Meta
- Include output of
pyinfra --support
.
System: Linux
Platform: Linux-5.15.62-x86_64-with-glibc2.34
Release: 5.15.62
Machine: x86_64
pyinfra: v2.4
Executable: /nix/store/722hn0z9f2mrmw2lba3ayjk2f3pz592g-python3.9-pyinfra-2.1/bin/pyinfra
Python: 3.9.13 (CPython, GCC 11.3.0)
- How was pyinfra installed (source/pip)?
Nix (nix-shell to be specific), built from 2.4 source
- Include pyinfra-debug.log (if one was created)
- Consider including output with
-vv
and--debug
.
--> Loading config...
--> Loading inventory...
[pyinfra_cli.inventory] Creating fake inventory...
[pyinfra_cli.inventory] Checking possible group_data directory: /homelab
[pyinfra_cli.inventory] Checking possible group_data directory: /homelab/inventory
--> Connecting to hosts...
[pyinfra.connectors.ssh] Connecting to: synology ({'allow_agent': True, 'look_for_keys': True, 'hostname': '[REDACTED]', '_pyinfra_ssh_forward_agent': None, '_pyinfra_ssh_config_file': None, '_pyinfra_ssh_known_hosts_file': None, '_pyinfra_ssh_strict_host_key_checking': None, '_pyinfra_ssh_paramiko_connect_kwargs': None, 'username': '[REDACTED]', 'port': [REDACTED], 'timeout': 10, 'password': '[REDACTED]'})
[pyinfra.connectors.sshuserclient.client] Loading SSH config: None
[synology] Connected
[pyinfra.api.state] Activating host: synology
--> Preparing operations...
Loading: deploys/synology/[REDACTED].py
[pyinfra.api.host] Starting deploy Deploy docker compose file (args={'sudo': False, 'sudo_user': None, 'use_sudo_login': False, 'use_sudo_password': '[REDACTED]', 'preserve_sudo_env': False, 'su_user': None, 'use_su_login': False, 'preserve_su_env': False, 'su_shell': None, 'doas': None, 'doas_user': None, 'shell_executable': 'sh', 'chdir': None, 'env': {}, 'success_exit_codes': [0], 'timeout': None, 'get_pty': None, 'stdin': None, 'name': None, 'ignore_errors': False, 'continue_on_error': False, 'precondition': None, 'postcondition': None, 'on_success': None, 'on_error': None, 'parallel': 2, 'run_once': False, 'serial': False}, data=None)
[pyinfra.api.operation] Adding operation, {'Deploy docker compose file | Files/Template'}, opOrder=(0, 7, 9), opHash=ce735ef7f0d2bdf463e7b274d1af100e588930c8
[pyinfra.api.facts] Getting fact: files.File (path=./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml) (ensure_hosts: None)
[pyinfra.connectors.ssh] Running command on synology: (pty=False) sh -c '
temp=$(mktemp /tmp/pyinfra-sudo-askpass-XXXXXXXXXXXX)
cat >"$temp"<<'"'"'__EOF__'"'"'
#!/bin/sh
printf '"'"'%s\n'"'"' "$PYINFRA_SUDO_PASSWORD"
__EOF__
chmod 755 "$temp"
echo "$temp"
'
[pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 0
[pyinfra.connectors.ssh] Running command on synology: (pty=None) env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-gCs6HOfttNgK *** sh -c '! (test -e ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml || test -L ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml ) || ( stat -c '"'"'user=%U group=%G mode=%A atime=%X mtime=%Y ctime=%Z size=%s %N'"'"' ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml 2> /dev/null || stat -f '"'"'user=%Su group=%Sg mode=%Sp atime=%a mtime=%m ctime=%c size=%z %N%SY'"'"' ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml )'
[pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 0
[pyinfra.api.facts] [synology] Loaded fact files.File (path=./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml)
[pyinfra.api.facts] Getting fact: files.Directory (path=./tmp/[REDACTED]/docker-compose.yml) (ensure_hosts: None)
[pyinfra.connectors.ssh] Running command on synology: (pty=None) env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-gCs6HOfttNgK *** sh -c '! (test -e ./tmp/[REDACTED]/docker-compose.yml || test -L ./tmp/[REDACTED]/docker-compose.yml ) || ( stat
-c '"'"'user=%U group=%G mode=%A atime=%X mtime=%Y ctime=%Z size=%s %N'"'"' ./tmp/[REDACTED]/docker-compose.yml 2> /dev/null || stat -f '"'"'user=%Su group=%Sg mode=%Sp atime=%a mtime=%m ctime=%c size=%z %N%SY'"'"' ./tmp/[REDACTED]/docker-compose.yml )'
[pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 0
[pyinfra.api.facts] [synology] Loaded fact files.Directory (path=./tmp/[REDACTED]/docker-compose.yml)
[pyinfra.api.facts] Getting fact: files.Sha1File (path=./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml) (ensure_hosts: None)
[pyinfra.connectors.ssh] Running command on synology: (pty=None) env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-gCs6HOfttNgK *** sh -c 'test -e ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml && ( sha1sum ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml 2> /dev/null || shasum ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml 2> /dev/null || sha1 ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml ) || true'
[pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 0
[pyinfra.api.facts] [synology] Loaded fact files.Sha1File (path=./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml)
[pyinfra.api.host] [synology] noop: file ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml is already uploaded
[pyinfra.api.operation] Adding operation, {'Deploy docker compose file | Server/Shell'}, opOrder=(0, 7, 16), opHash=4613229f58e989b5caf7c3eb0b4b6a2674276978
[pyinfra.api.operation] Adding operation, {'Deploy docker compose file | Files/File'}, opOrder=(0, 7, 18), opHash=9eb8fef4b14176505e5ff37f9abe8592215b262a
[pyinfra.api.host] Reset deploy to None (args=None, data=None)
[synology] Ready: deploys/synology/[REDACTED].py
--> Proposed changes:
Groups: inventory / infra
[synology] Operations: 3 Change: 2 No change: 1
--> Beginning operation run...
--> Starting operation: Deploy docker compose file | Files/Template (deploys/synology/docker-compose/[REDACTED].yml, ./tmp/[REDACTED]/docker-compose.yml/docker-compose.yml, create_remote_dir=True)
[pyinfra.api.operations] Starting operation Deploy docker compose file | Files/Template on synology
[synology] No changes
--> Starting operation: Deploy docker compose file | Server/Shell (cd ./tmp/[REDACTED]/docker-compose.yml && docker-compose up -d)
[pyinfra.api.operations] Starting operation Deploy docker compose file | Server/Shell on synology
[pyinfra.connectors.ssh] Running command on synology: (pty=None) env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-TF51VUsf7Fqy *** sudo -H -A -k sh -c 'cd ./tmp/[REDACTED]/docker-compose.yml && docker-compose up -d'
[pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 1
[synology] sudo password:
[pyinfra.connectors.ssh] Running command on synology: (pty=None) env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-TF51VUsf7Fqy *** sudo -H -A -k sh -c 'cd ./tmp/[REDACTED]/docker-compose.yml && docker-compose up -d'
[pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 1
[synology] sudo: unable to run /tmp/pyinfra-sudo-askpass-TF51VUsf7Fqy: Permission denied
[synology] sudo: no password was provided
[synology] sudo: a password is required
[synology] Error: executed 0/1 commands
[pyinfra.api.state] Failing hosts: synology
[pyinfra.connectors.ssh] Running command on synology: (pty=False) sh -c 'rm -f /tmp/pyinfra-sudo-askpass-TF51VUsf7Fqy' [pyinfra.connectors.ssh] Waiting for exit status...
[pyinfra.connectors.ssh] Command exit status: 0
--> pyinfra error: No hosts remaining!
(there are some weird directory structure in the logs above, please disregard, most likely a bug in my scripts)
Issue Analytics
- State:
- Created a year ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
Oh no, since my PR broke this I’ll submit a PR to fix it.
Thank you for raising this @Renerick! I think the updated askpass handling from #852 should indeed respect the temp dir config.