question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't configure the location of `pyinfra-sudo-askpass-XXXXXXX` file, sudo failing in environments with restricted /tmp script execution

See original GitHub issue

Describe 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:closed
  • Created a year ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
jaysoffiancommented, Sep 19, 2022

Oh no, since my PR broke this I’ll submit a PR to fix it.

2reactions
Fizzadarcommented, Sep 4, 2022

Thank you for raising this @Renerick! I think the updated askpass handling from #852 should indeed respect the temp dir config.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Restricting Script Execution in the /tmp Directory - Plesk Forum
Hi, i'm using PLesk Onyx Servers. Is it important to create a new tmp Partition? Will this be same like this Tutorial shows...
Read more >
Unable to execute script resource due to missing tmp directory
I was not able to execute the script until I created /tmp/rundeck with ... default rundeck tmp dir location, or change the spec-file...
Read more >
User root can't write to file in /tmp owned by someone else in ...
The root user should always be able to edit any and all files. The only correct response is to disable the sysctl fs.protected_regular...
Read more >
Jenkins Pipeline job can't find script due to @tmp path being ...
The Jenkinsfile and script exist in the same directory and yet the job fails to find the script to run. This is the...
Read more >
Agent install fails with disk space required
The server has limited space available in the /tmp directory, we set $INSTBASE to /var/tmp directory with more space.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found