Python subprocess call sudo passwordless - subprocess

I am currently working in a remote environment which has a user with certain sudo permissions for which it does not require inputting any password.
Specifically it can perform some nginx commands without the need of a password, so far so good. The problem I face comes when I have a python script that takes care of checking for updates and if there are changes tries to reload nginx. As seen below
Popen(['sudo', 'nginx', '-T'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
call(["sudo", "systemctl", "reload", "nginx.service"])
When the script reaches one of this steps a prompt pops up on the terminal asking for a password, which should not be necessary since the user running the script has the permissions to run the commands without inputting it.
Question: Is there maybe a way, without hardcoding the password in a variable, to tell the script to "inherit" the permissions of the user when I run it?
Some additional information:
If the script itself is invoked with sudo everything works, but sadly this is not an option and sudo should be used only for the specific parts that completely require it (nginx reloads)
Python version is 3.5
EDIT: Solved this thanks to a friend:
The solution was to add the 'shell=True' paramater to the Popen.
Popen('sudo nginx -T'], shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)

The issue might be, that there is a mismatch in the sudoers nginx-path and the PATH variable used during script execution.
Try to either match the Popen call to the full PATH given in the sudoers file or adjust the PATH in the shell calling the Python script.

Related

Interactively call SCP from Powershell

I've been banging my head against a powershell shaped wall all day. For work reasons, I want to be able to upload a file from a windows machine to a remote linux box. There's some work to do before so I foolishly believed I could just drop in a call to SCP in my script. But it doesn't like it one bit:
Putting
scp api.zip ${user}#${currEnv}:/${uploadLocation}
where user is the remote login name, currEnv is the ip address and uploadLocation is /tmp (at least while I'm debugging)
in the code just causes the execution to hang completely - in fact the same thing happens if I run that command from the PS command line, even if I manually replace all the variables.
I tried replacing it with pscp which works better in that it actually connects, but then throws up the usual warning about this being the first time I've connected and should type 'y' to proceed (again, even from the command line iteself) - but that won't let me type anything in. I've also even tried using wsl scp ... to run it (don't tell the IT guy), but that also seems to hang - it shows me the server banner, but never gets to the bit where it should be asking for my remote password.
Am I missing something?

Redirect WSL input in Powershell

I've been trying to write a powershell script that automates my windows workspace setup and configuration and am currently stuck trying to redirect input to WSL when executing it for the first time. The core of the problem is that Ubuntu's first launch prompts for a username and password, then logs in to a bash shell. I tried writing down the input lines into a text file like so:
Username
Password
Password
exit
Then, I tried redirecting the input of wsl to the file:
Start-Process ubuntu2004.exe -RedirectStandardInput stdin.txt -NoNewWindow -Wait
The above didn't work as executing WSL just starts spamming Enter new UNIX username: adduser: only one or two names allowed. I tried doing same in CMD with the < input redirection, but the result is the same.
This is not exactly the answer to your question, but in my opinion, ansible is better suited for such a task.
I myself recently became interested in assembling a workspace in wsl and ansible seemed to me the best solution.
Before starting the build, you will need to perform minimal steps (create a user and install several packages, all this can be placed in the readme), but then there will be no restrictions.
You can find several ready-made examples of wsl assembly via ansible on github.
A few ideas for setting the username/password in a new Ubuntu WSL instance:
First, a "PowerShell sendkeys" via COM or Interop might work for this. It's probably the closest in behavior to what you are actually asking.
Second, and perhaps most promising, I just tried this with a new Debian WSL installed from the Store (since I didn't want to mess with my Ubuntu install).
When running debian.exe (like ubuntu2004.exe), I let it run the install, then I Ctrl+C'd out of it when it started asking for the default username/password. At that point, the WSL instance is installed, but with only root. I assume that your script can let the command run for a certain period of time, then kill the process to replicate this.
From your script, you should then be able to run wsl -u root useradd --create-home --user-group --groups adm,dialout,cdrom,floppy,sudo,audio,dip,video,plugdev,netdev --password "encryptedPassword" username (see here for creating the encrypted password). I think that will get you a stock Ubuntu user the way that WSL sets it up.
You'll then need to either create a /etc/wsl.conf file (instructions) letting the instance know that that user is the default, or LxRunOffline lists this as one of its features.
But I'd also throw in that you might just want to keep a "backup" of an existing WSL instance that you start from. Do a wsl --export <distroname> <imagename.tgz>, then you can import it when setting up the new Windows host by copying the tgz over and doing a wsl --import <DistroName> <DirectoryWhereYouwantItToLive> <imagename.tgz>.
If you want, you can keep this image up to date with your desired WSL configuration, so that you don't have to recreate it when you rebuild the Windows hosts. That said, this is where I do follow #Mystic's suggestion of using Ansible to store my WSL "configuration as code". It allows me to not only recreate my WSL instances, but also that same configuration when I set (or reset) a Linode host or another Linux system.

Run command that requires UAC trough command line

I have a bunch of virtual machines that I need to update from time to time. I found this VirtuaBox command
VBoxManage guestcontrol
that works great. problem is that updating requires UAC. Is there any way to bypass the UAC check
The way I found to do it quickly was to buy this software:
http://www.ntwind.com/software/hstart.html
If I had more time I would probably develop something myself. What the software does is install a scheduled task and then run the program through the scheduled task. A brief description of this can be found here:
http://www.howtogeek.com/howto/windows-vista/create-administrator-mode-shortcuts-without-uac-prompts-in-windows-vista/
If I understand correctly, you are requested to type in the root password every time, right?
If so, to bypass that by adding the command to the sudoers file, then when using the command (with sudo) it will not ask for a password but will elevate you to root right away.
To allow a specific program or shell script to run as root but without typing the password (like during boot), add to /etc/sudoers the following line:
(username) ALL = NOPASSWD: /path/to/cmd
for example:
Mac ALL = NOPASSWD: /usr/bin/vboxmanage
After doing that, when typing sudo vboxmanage you will not be ask for root password anymore.
Hope that helps!

How to open Perl file handle to write data via sudo (or as another user)

I'd like to write data to a file, but the file handle should be opened with access permissions for a specific user.
Thus, the following statement:
open (FH, "> $filename") or die "$#\n";
would allow writing to a file as that particular user.
Is there a way to do this within a Perl script, without the entire script being run with sudo -u $username?
There are two established ways. Stackers, you are invited to edit this answer to fill in the drawbacks for each.
Run the program with sudo. The first thing you do in the program is to open the files you need and keep the handles, and then immediately afterwards drop the root privileges. Any further processing must take place with low privileges. The Apache httpd works likes this, it opens the log files as root, but continues running as nobody or similar.
If you don't like that way, run the program normally, and when you need to elevate, create a new process and have it run with a user configured sudo, su -, kdesu/gksu or whatnot. The CPAN client works likes this, it fetches, unpacks, builds and tests a module as a normal user, but calls sudo make install etc. when it's time to install.
An alternative to daxim's suggestions is to have the script owned by the specific user and have the script permissions include the setuid and/or setgid bits.

Is it possible to have Perl run shell script aliases?

Is it possible to have a Perl script run shell aliases? I am running into a situation where we've got a Perl module I don't have access to modify and one of the things it does is logs into multiple servers via SSH to run some commands remotely. Sadly some of the systems (which I also don't have access to modify) have a buggy SSH server that will disconnect as soon as my system tries to send an SSH public key. I have the SSH agent running because I need it to connect to some other servers.
My initial solution was to set up an alias to set ssh to ssh -o PubkeyAuthentication=no, but Perl runs the ssh binary it finds in the PATH instead of trying to use the alias.
It looks like the only solutions are disable the SSH agent while I am connecting to the problem servers or override the Perl module that does the actual connection.
Perhaps you could put a command called ssh in PATH ahead of the ssh which runs ssh as you want it to be run.
Alter the PATH before you run the perl script, or use this in your .ssh/config
Host *
PubkeyAuthentication no
Why don't you skip the alias and just create a shell script called ssh in a directory somewhere, then change the path to put that directory before the one containing the real ssh?
I had to do this recently with iostat because the new version output a different format that a third-party product couldn't handle (it scanned the output to generate a report).
I just created an iostat shell script which called the real iostat (with hardcoded path, but you could be more sophisticated), passing the output through an awk script to massage it into the original format. Then, I changed the path for the third-party program and it started working fine.
You could declare a function in .bashrc (or .profile or whatever) with that name. It could look like this (might break):
function ssh {
/usr/bin/ssh -o PubkeyAuthentication=no "$#"
}
But using a config file might be the best solution in your case.