With the subprocess.Popen we can call any executable under the currently logged-in user credentials like so:
import subprocess
cmd = ['C:\Windows\system32\executable.exe']
proc = subprocess.Popen(cmd, cwd=os.path.dirname(RAR_EXE), stdout=subprocess.PIPE)
output = proc.stdout.read()
Would it be possible to call and execute the same executable.exe under another user credentials assuming that the user's name and the password are known, such as:
username = 'steve'
password = 'password123`
This question doesn't really have anything to do with Python. You're just asking how to execute a command as another user from the Windows command line. The runas program will do that for you:
Usage as given in the link:
runas [{/profile | /noprofile}] [/env] [{/netonly | /savecred}] [/smartcard] [/showtrustlevels] [/trustlevel] /user: " "
Where:
/profile
Loads the user's profile. This is the default. This parameter cannot be used with the /netonly parameter.
/no profile
Specifies that the user's profile is not to be loaded. This allows the application to load more quickly, but it can also cause a malfunction in some applications.
/env
Specifies that the current network environment be used instead of the user's local environment.
/netonly
Indicates that the user information specified is for remote access only. This parameter cannot be used with the /profile parameter.
/savecred
Indicates if the credentials have been previously saved by this user. This parameter is not available and will be ignored on Windows Vista Home or Windows Vista Starter Editions. This parameter cannot be used with the /smartcard parameter.
/smartcard
Indicates whether the credentials are to be supplied from a smartcard. This parameter cannot be used with the /savecred parameter.
/showtrustlevels
Displays the trust levels that can be used as arguments to /trustlevel.
/trustlevel
Specifies the level of authorization at which the application is to run. Use /showtrustlevels to see the trust levels available.
/user: " "
Specifies the name of the user account under which to run the program, the program name, and the path to the program file. The user account name format should be # or \.
/?
Displays help at the command prompt.
It doesn't look like there's any built-in way to provide the user's password, so you'll have to set up input and output pipes to be able to provide it when prompted. You may find this task easier with Pexpect, which is a third-party module for automating subprocess keyboard interaction.
Related
I am using pyVmomi for my automation. Now I am testing a VM, where the SSH is disabled by default, and I must change the password upon the first login:
You are required to change your password immediately (root enforced)
If I try connecting using pyVmomi's StartProgramInGuest, I get vim.fault.InvalidGuestLogin exception:
Failed to authenticate with the guest operating system using the supplied credentials
I am looking for a way to change the default password programmatically, (preferably) using pyVmomi
To start off, it seems like you failed to pass the correct credentials when calling the "StartProgramInGuest" function, you can specify and pass credentials to this function using Name-Password authentication, like below.
creds = vim.vm.guest.NamePasswordAuthentication(username='username', password='password)
Test this and make sure you successfully authenticated to the guest virtual machine. After you're able to successfully authenticate, you can use Process Manager, to create either a Linux process or Windows process to change your password. For example, here is a PowerShell process tested on a Windows 10 virtual machine, executed through StartProgramInGuest.
argument= vim.vm.guest.ProcessManager.ProgramSpec(programPath='powershell.exe -Command', arguments='"& {net user loginid newpassword;}"')
res = pm.StartProgramInGuest(vm, creds, argument)
Let me know if you need any clarification!
I created a Spotipy script that pulls the last 50 songs I listened to and adds them, and their audio features, to a Google Sheets. However, I'd love to be able to run this script daily without me manually having to run it, but I have very little experience with CRON scheduling. I'm having trouble wrapping my head around how it can be run given all of the command line arguments I need to enter.
The code requires multiple command line arguments passed first, such as
export SPOTIPY_REDIRECT_URI="http://google.com"
export SPOTIPY_CLIENT_SECRET='secret'
and similar for the client ID.
Additionally, the first argument after the script call is the username username = sys.argv[1].
Most importantly, it prompts me to copy and paste a redirect URL into the command line, which is unique each run.
Is it at all possible to pass the redirect URL to the command line each time the script is run using CRON?
I think what you're looking to accomplish can be achieved in one of two ways.
First, you could write a shell script to handle the export commands and passing the redirect URI to your script. Second, with a few tweaks to your script, you should be able to run it headlessly, without the intermediary copy/paste step.
I'm going to explore the second route in my answer.
Regarding the environment variables, you have a couple options. Depending on your distribution, you may be able to set these variables in the crontab before running the job. Alternatively, you can set the exports in the same job you use to run your script, separating the commands by semicolon. See this answer for a detailed explanation.
Then, regarding the username argument: fortunately, script arguments can also be passed via cron. You just list the username after the script's name in the job; cron will pass it as an argument to your script.
Finally, regarding the redirect URI: if you change your redirect URI to something like localhost with a port number, the script will automatically redirect for you. This wasn't actually made clear to me in the spotipy documentation, but rather from the command line when authenticating with localhost: "Using localhost as redirect URI without a port. Specify a port (e.g. localhost:8080) to allow automatic retrieval of authentication code instead of having to copy and paste the URL your browser is redirected to." Following this advice, I was able to run my script without having to copy/paste the redirect URL.
Add something like "http://localhost:8080" to your app's Redirect URI's in the Spotify Dashboard and then export it in your environment and run your script--it should run without your input!
Assuming that works, you can put everything together in a job like this to execute your script daily at 17:30:
30 17 * * * export SPOTIPY_REDIRECT_URI="http://localhost:8080"; export SPOTIPY_CLIENT_SECRET='secret'; python your_script.py "your_username"
I'm running a daemon as a service on a Windows server that's meant to listen to triggers and create folders on a server. However I ran into difficulty with the fact that though the command prompt recognise my 'Y:' drive mapping, the service does not.
Looking into it, I was advised that the issue was likely that the mapping was not universally set up. So I tried to get the service to run the net use command and map the same drive at that level of access.
Note: The daemon uses logger.info to write to a text file.
command = ['net', 'use','Y', '\\\\REAL.IP.ADDRESS\\FOLDER',
'/user:USER', 'password']
response = subprocess.Popen(command,stdout=subprocess.PIPE)
result = response.communicate()
logger.info("net use result:")
logger.info(result[0])
logger.info(result[1])
command = ['net', 'use',]
response = subprocess.Popen(command,stdout=subprocess.PIPE)
result = response.communicate()
logger.info("Current drives:")
logger.info(result[0])
logger.info(result[1])
However when running that I got no response at all from the process, and then a response telling me that there are no current drives.
INFO - net use result:
INFO -
INFO - None
INFO - Current drives:
INFO - New connections will be remembered. There are no entries in the list.
INFO - None
Maybe I'm dumb but shouldn't it return something in response, especially if it's failing to execute the command? Or am I actually not able to map drives at this level?
Note: The daemon's logger module prepends every line with INFO - so for the purpose of this question you can ignore that.
By default, services run under the Local System account and cannot access network resources. If you want to be able to access your network from a service, try running the service as a user with network privileges. (Note that this may be a security concern!)
In the Services panel, go to the Properties of your service and click the Log On tab. Select This account and specify the user credentials.
When I tried to create file to a shared folder I got an error Permission denied: ' tp create the file. I know a different username and password to create the file in that share folder. How can I use it with the Open function.
The Open function I used is as given below.
with open(rootDirectory+"\\"+"test.txt", "a") as NewFile:
NewFile.write(filedata);
Thanks,
There is no magical way to change the way you call open to do this for you. You have to interact with the Win32 security system in some way.
The first option is to impersonate the other user. Then, anything you do—including open, or anything else—is done as if you were that user. If you have pywin32, you can use its win32security wrappers to do this. You should read the MSDN docs on LogonUser, LogonUserEx, and ImpersonateLoggedOnUser to understand how this works. But it will look something like this:
user = LogonUser(username, None, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT)
try:
ImpersonateLoggedOnUser(user)
with open(rootDirectory+"\\"+"test.txt", "a") as NewFile:
NewFile.write(filedata)
finally:
RevertToSelf()
CloseHandler(user)
Of course you probably want some error handling, and you might want to create some context-manager wrappers instead of using a finally block, and so on. And again, read the docs to decide which function you want to call and which arguments you want to pass. But this should get you started.
As a variation on this, you can run a child process as that other user. That doesn't require impersonation (which you may not have the SeImpersonatePrivilege privileges to do). It's also much easier to port to Unix if you ever need to do that. See CreateProcessWithLogon for details.
A simpler way to do the same thing is to not do it from Python, but from the shell. Launch your script with the RunAs command instead of launching it directly. Or, if you can't do that, take the part that needs to run as the other user, move it into another script, then subprocess the RunAs command to launch it.
Alternatively, if you have sufficient rights (or can elevate to Administrator privileges to get those rights), you can just change the ACLs on the file to give yourself the write permission you don't have. In some cases, just doing os.chmod is sufficient for that, but usually not; you will have to pywin32 the native Win32 APIs again.
New to Stackoverflow, so first off, hello.
I'm working on a little project for my school which is supposed to be a custom gui (written in python as an educational challenge for me since I've never used python) for the open source Unison program. We're trying to allow students and staff to sync a folder at home and the school by launching this program with as little input as possible (idiot-proofing if you will). The interface is supposed to be just they're school username and password and the gui wrapper should just send the username and password to Unison and sync them.
The problem is Unison in turn launches SSh and prompts for the password but python subprocess.communicate(input) method won't let ssh take the password. I realized ssh will only accept input from the terminal and I can't figure out how to trick it. I've read some stuff about using a pseudo terminal but I'm still stumped. RSA keys would be the ideal solution, but generating them and then placing them on the remote server still involves me needing to login with a password at least once and that would require a solution to the above, or the terminal which is not idiot proof.
def startSync(self):
'''
'''
userName = self.userNameIn.get()
userPass = self.userPassIn.get()
localDir = "/Users/localuser/syncFolder/"
remoteDir = " ssh://schoolServer/remotesyncFolder" #for testing purposes, I set this to my own home machine which logs into my own account if I don't provide me#myserver.net
unisonExecRemotePath = " -servercmd /Users/RemoteMe/unison" #unison is the unix executable responsible for launching unison on the remote system
silenceCmdPrompts = " -silent" #keeps unison from displaying directory differences and asking if its okay to sync
executionString = "./unison" + localDir + remoteDir + unisonExecRemotePath + silenceCmdPrompts
mainProcess = subprocess.Popen(executionString,shell = True, stdin = subprocess.PIPE)
mainProcess.communicate(userPass)
The execution strings works fine in there terminal if I paste it in. And any general python tips would also be appreciated if you're so inclined.
Thanks!
Unison User Manual: http://www.cis.upenn.edu/~bcpierce/unison/download/releases/stable/unison-manual.html
Edit: I should also note that while I'm currently developing under OSX and Linux, I will eventually have to make this windows compatible since most of my school's students run windows as their primary (or only) machine.
Look into pexpect.
import pexpect
child = pexpect.spawn('ssh myname#host.example.com')
child.expect('Password:')
child.sendline(mypassword)
child.interact()
If you want to send a password to ssh you need to open pseudoterminal (a pty) and talk to it using that instead of just using stdin/stdout. Take a look at the pexpect module, which is designed to do exactly that.
An alternative solution would involve some sort of out-of-band mechanism for distributing public keys: for example, set up a simple web application where people can paste in a public key and have it manage the authorized_keys file on behalf of the user.