Change guest password using pyvmomi - python

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!

Related

Alternative to attempting to persist Environment Variables in Python

Up until now, whenever I have needed to store a "secret" for a simple python application, I have relied on environment variables. In Windows, I set the variables via the Computer Properties dialog and I access them in my Python code like this:
database_password = os.environ['DB_PASS']
The simplicity of this approach has served me well. Now I have a project that uses Oauth2 authentication and I have a need to store tokens to the environment that may change throughout program execution. I want them to persist the next time I execute the program. This is what I have come up with:
#fetch a new token
token = oauth.fetch_token('https://api.example.com/oauth/v2/token', code=secretcode)
access_token = token['access_token']
#make sure it persists in the current session
os.environ['TOKEN'] = access_token
#store to the system environment (Windows)
cmd = 'SETX /M TOKEN ' + access_token
os.system(cmd)
It gets the job done quickly for me today, but does not seem like the right approach to add to my toolbox. Does anyone have a more elegant way of doing what I am trying to do that does not add too many layers of complexity? If the solution worked across platforms that would be a bonus.
I have used the Python keyring module with great success. It's an interface to credential vaults provided by the operating system (e.g., Windows Credential Manager). I haven't used it on Linux, but it appears to be supported, as well.
Storing a password/token and then retrieving it can be as simple as:
import keyring
keyring.set_password("system", "username", "password")
keyring.get_password("system", "username")

Fabric2 CLI: gracefully switch SSH user

I am using Invoke/Fabric with boto3 to create an AWS instance and hand it over to an Ansible script. In order to do that, a few things have to be prepared on the remote machine before Ansible can take over, notably installing Python, create a user, and copy public SSH keys.
The AWS image comes with a particular user. I would like to use this user only to create my own user, copy public keys, and remove password login afterwards. While using the Fabric CLI the connection object is not created and cannot be modified within tasks.
What would be a good way to switch users (aka recreate a connection object between tasks) and run the following tasks with the user that I just created?
I might not go about it the right way (I am migrating from Fabric 1 where a switch of the env values has been sufficient). Here are a few strategies I am aware of, most of them remove some flexibility we have been relying on.
Create a custom AMI on which all preparations has been done already.
Create a local Connection object within a task for the user setup before falling back to the connection object provided by the Fabric CLI.
Deeper integrate AWS with Ansible (the problem is that we have users that might use Ansible after the instance is alive but don't have AWS privileges).
I guess this list includes also a best practice question.
The AWS image comes with a particular user. I would like to use this user
only to create my own user, copy public keys, and remove password login
afterwards. While using the Fabric CLI the connection object is not created
and cannot be modified within tasks.
I'm not sure this is accurate. I have switched users during the execution of a task just fine. You just have to make sure that all subsequent calls that need the updated env use the execute operation.
e.g.
def create_users():
run('some command')
def some_other_stuff():
run('whoami')
#task
def new_instance():
# provision instance using boto3
env.host = [ ip_address ]
env.user = 'ec2-user'
env.password = 'sesame'
execute(create_users)
env.user = 'some-other-user'
execute(some_other_stuff)

How to run python process as another Windows user

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.

How is python-keyring implemented on Windows?

How does python-keyring provide security on Windows?
In GNOME/KDE on Linux, the user is prompted to enter his password to authorize access to the keyring on a per-application basis.
In Windows there is no such prompt when an application accesses the keyring. What is stopping a random python application to retrieve a password from the keyring by running
import keyring
get_password(service, username)
How is user consent implemented? Is the whole concept, atleast in Windows, based on the assumption that all installed programs are 'trusted'?
Researching this a bit, it appears that the passwords are stored within a Windows Credential Vault, which is the equivalent of the Gnome or KDE keyrings. You can actually see the ones that you have stored by opening up the Windows Credential Manager. I get there by just typing in Credential Manager on Windows 8.1 from the start screen, but I think you can get to it from the User accounts page as well.
Anyway, as you can see from the attached image, the password that I added to the keyring as a test is displayed under Windows Credentials -> Generic Credentials -> keyring_demo. Opening this window up as another user on the PC does not show this password, so it seems secured from other Users. This screen also allows you to revoke or change passwords.
As to how consent is implemented, I believe keyring will operate as long as your Windows user account is logged in, but I don't know the specifics.
the cedential manager method works, but in my case add:
internet or network addess "myPassGroup"
username "pass1"
password "xxx"
then add another entry using the same network address
internet or netwokr address "myPassGroup"
username "pass2"
password "xxx"
the pass2 will OVERRIDE the frist entry pass1!
this is a major drewback, as the "internet or network address" is
served as a groupname in keyring, I need put mutiple password under
the same name
my solution is to use the python command direct
open CMD in windows
type Python
then type import keyring
then type keyring.set_password("groupName", "passKey" ,"password")
then type keyring.set_password("groupName", "passKey2" ,"password2")
you can validate the result by
keying.get_password("groupname", "passKey")
keying.get_password("groupname", "passKey2")
I konw this will work, but still struggle to find where the actual data
is saved
I used the following command try to find out
python -c "import keyring.util.platform_; print(keyring.util.platform_.config_root())"
python -c "import keyring.util.platform_; print(keyring.util.platform_.data_root())"
the data_root in my case is "C:\Users\JunchenLiu\AppData\Local\Python Keyring"
I checked the folder, it doesn't exists... it must been saved somewhere. maybe someone can figure it out.
but my solution should work prefectly on Windows
This is from the python-keyring github I imagine a similar concern exists for windows as does MacOS though the website says no analysis has been completed
Security Considerations
Each builtin backend may have security considerations to understand before using this library. Authors of tools or libraries utilizing keyring are encouraged to consider these concerns.
As with any list of known security concerns, this list is not exhaustive. Additional issues can be added as needed.
macOS Keychain
Any Python script or application can access secrets created by keyring from that same Python executable without the operating system prompting the user for a password. To cause any specific secret to prompt for a password every time it is accessed, locate the credential using the Keychain Access application, and in the Access Control settings, remove Python from the list of allowed applications.
from keyring.backend import KeyringBackend
class SimpleKeyring(KeyringBackend):
"""Simple Keyring is a keyring which can store only one
password in memory.
"""
def __init__(self):
self.password = ''
def supported(self):
return 0
def get_password(self, service, username):
return self.password
def set_password(self, service, username, password):
self.password = password
return 0
def delete_password(self, service, username):
self.password = None

How to deal with interactive API in python

I'm in a situation where I need to pass some texts to a prompt generate by a API (seems for API it's a pretty weird behavior, this is the first time I ran into this), like below:
kvm_cli = libvirt.open("qemu+ssh://han#10.0.10.8/system")
then a prompt shows up asking for the ssh password (password for 10.0.10.8 is:), I have to manually type it there in order to move on and yield the kvm_cli object I needed.
I tried to use the pexpect module to deal with this however it's for OS command line instead of API.
It's also possible to work around this by using ssh certification files but it's not a favorable authentication approach in our scenario.
Since our wrapper to the 'open' method is not interactive, we cannot ask the user to input the password, do you guys have any thought how could I address it?
I am not a libvirt user, but I believe that the problem is not in the library, but in the connection method. You seem to be connecting via ssh, so you need to authenticate yourself.
I've been reading the libvirt page on ArchWiki, and I think that you could try:
setting up the simple (TCP/IP socket) connection method, or
setting up key-based, password-less SSH login for your virtual host.

Categories