How to make Passwd::Keyring::Auto persistent on Windows - windows

I'm using Passwd::Keyring::Auto for Perl on Windows. I noticed that the keyring is not persistent.
Can I force it to be persistent on Windows?
http://search.cpan.org/~mekk/Passwd-Keyring-Auto-0.2703/lib/Passwd/Keyring/Auto.pm
Ex.
use Passwd::Keyring::Auto;
my $keyring = get_keyring(app=>"Test", group=>"Windows");
my $username = "someuser";
my $password = $keyring->set_password($username, $password, "mylostspace.com");
When my program ends, I'd like to get whatever passwords I had in the keyring like below:
$password = $keyring->get_password($username, "sometest.com");
However, the $keyring->is_persistent() always returns 0. I tried forcing the option PERSISTENT => 1 when I create the keyring, but that didn't work.
Thanks in advance

I simply haven't developed windows backend yet, as I do not own windows machine at the moment. Writing module like Passwd::Keyring::WindowsVault (or similar) should not be hard (especially considering one can consult python keyring library source for inspiration), but requires some programmer with Windows development environment. In case you are (or anybody else is) interested in writing one, I would be glad to help, but I am simply unable to test such a module or even to prepare binary distribution for CPAN.
Once such module exists, integrating it into Passwd::Keyring::Auto would be trivial
Pointers:
(what should Passwd::Keyring backend implement)
https://metacpan.org/pod/distribution/Passwd-Keyring-Auto/lib/Passwd/Keyring/Auto/KeyringAPI.pm
(APIs used by pythonic library)
https://bitbucket.org/kang/python-keyring-lib/src/8aadf61db38c70a5fe76fbe013df25fa62c03a8d/keyring/backends/Windows.py?at=default
(in perl it should be replaced with some XS as I do not know about anything like ctypes, module code structure would likely be similar to that of https://bitbucket.org/Mekk/perl-keyring-gnome/src )

And one more note: with some effort it should be possible to use Passwd::Keyring::PwSafe3 backend on Windows, to keep passwords persistent. You will still need to provide opening password for this storage (no open thanks to OS authorization) on every run but in case you have multiple passwords or want to manage them from GUI too it may make sense. You can try setting environment variable PASSWD_KEYRING_AUTO_PREFER to PwSafe3 to use this keyring (of course install the module beforehand).

Related

Can I replace %USERPROFILE% and still get KNOWNFOLDERIDs from the registry?

We're developing an open source Python library that runs on Linux, MacOS, and Windows, but we don't have much experience or exposure to Windows in the developer team. The way we setup and run our test suite works fine under Linux and Mac, but is suboptimal on Windows.
Our tests set up a new directory in a temporary location, place a fake .gitconfig with relevant configurations inside it, and have the relevant HOME environment variables point to this location as the home directory in order to pick up the configurations during testing.
The code is shortened and can't be run, but hopefully illustrates the gist of what we do:
with make_tempfile(mkdir=True) as new_home:
pass
for v, val in get_home_envvars(new_home).items():
set_envvar(v, val)
if not os.path.exists(new_home):
os.makedirs(new_home)
with open(os.path.join(new_home, '.gitconfig'), 'w') as f:
f.write("""\
[user]
name = Tester
email = test#example.com
[more configs for testing]
exc = 1
""")
where get_home_envvars() makes sure that the $HOME env variable points to the new, temporary test home. On Windows since Python 3.8, os.path no longer queried the $HOME variable to determine a user's home, but USERPROFILE[1 ][2], so we've just overwritten this variable with the temporary test home:
def get_home_envvars(new_home):
environ = os.environ
out = {'HOME': new_home}
if on_windows:
# requires special handling, since it has a number of relevant variables
# and also Python changed its behavior and started to respect USERPROFILE only
# since python 3.8: https://bugs.python.org/issue36264
out['USERPROFILE'] = new_home
out['HOMEDRIVE'], out['HOMEPATH'] = splitdrive(new_home)
return {v: val for v, val in out.items() if v in os.environ}
However, we have now discovered that this breaks our test setup on Windows, with tests "bleeding" their caches, cookie data bases etc. into the places where we perform our unit tests, and with this creating files and directories that break our test assumptions.
I have a very limited understanding on what happens exactly, but my current hypothesis is this: Our library determines the appropriate locations for caches, logs, cookies, etc upon start by using appdirs [3], which does so by querying the "special folder" IDs/ CSIDLs that Windows has [4]. This information is determined in the Windows registry - which is found based on the USERPROFILE. To quote one specific reply in the Python bug tracker to this change:
This is unfortunate. Modifying USERPROFILE is highly unusual. USERPROFILE is the location of the user's "NTUSER.DAT" registry hive and local application data ("AppData\Local"), including "UsrClass.dat" (the "Software\Classes" registry hive). It's also the default location for a user's known shell folders and home directory. Modifying USERPROFILE shouldn't cause problems with any of this, but I'm not completely at ease with it.
After our testsuite setup is done, we start new processes that run our tests. The new processes only get to see the new USERPROFILE, and appdirs returns the paths it finds by sending them through normpath, which unfortunately interprets the empty string returned by _get_win_folder for a CSIDL that now can't be found anymore as a relative path (.):
# snippet from appdirs source code
path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
And based on this, we end up configuring the current working directory of each test as the place for user data, user caches, etc.
My question is: How could I fix this? Based on my probably incomplete understanding, I currently think it ultimately boils down to the question how to treat or mock the USERPROFILE. I need to have it pointed to a registry in order to derive the "special folder" IDs (be it with appdirs or more modern replacements of it) - but I also need it to point to the fake home with test-specific Git configurations. I believe the latter requires overwriting USERPROFILE in Python3.8 and newer. I'm wondering if there is a way to copy or mock the registry and place it under the new home? Set relevant CSIDLs/KNOWNFOLDERIDs in some other way? Hardcode other temporary locations to use as cache directories etc? Or maybe there is a more clever way to run a test suite under Windows that does not require a fake home?
I would be very grateful to learn from more experienced Windows developers what to do, or also what not to do. Many thanks in advance.
[1] https://docs.python.org/3.11/library/os.path.html#os.path.expanduser
[2] https://bugs.python.org/issue36264
[3] https://github.com/ActiveState/appdirs
[4] https://learn.microsoft.com/en-us/windows/win32/shell/csidl

windows registry storage best practice

Background
I've recently been shunted into the world of windows programming and I'm still trying to find my way around the best practices and ways of doing things. So I was just hoping for some pointers on use of the registry
Not particularly relevant but the background is that I am creating an installer in Golang, a couple of points to get out the way on that:
I am aware MSI's would usually be best practice for an installer (I have my reasons for going custom exe)
I know there are more obvious language choices than golang, just go with it
Current registry use
As part of the install process, I store several pieces of data in the registry:
run once commands:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
I create a few entries here: to restart the process after a system reboot and to delete some temp files on reboot after uninstall
an uninstall entry:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Vendor
Product
Content here is the same as an MSI would create, I was careful not to create any additional custom fields here (all static data until uninstall)
an application entry:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Vendor\Product
I store some additional data about the installation here, some of which is needed for uninstall such as state info from before installation (again all static content)
a temporary entry:
Computer\HKEY_CURRENT_USER\SOFTWARE\Vendor\Product
I store some temporary data here which can include some sensitive user entered data (usernames/passwords). I run some symmetric encryption to obscure the data though my understanding is this is area of the registry is encrypted so only the user could access anyway (would like confirmation on that)
This data is used to resume after restart and then deleted
Questions
I'm looking for confirmation / corrections on my current use of the registry?
I now have need to pass some data between an application and a running service, this data would be updated every 1-2 minutes and would be a few bytes of JSON. Does the registry seem like a reasonable place to store variable data like this? If so is there a particular place that better for variable data - I was going to add it to:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Vendor\Product
HCKU isn't encrypted to my knowledge. It's stored in a file called NTUser.dat and could be loaded as a hive under HKEY_USERS and visible to other processes with sufficient rights to do so.
You would need to open up the rights to HKLM\SOFTWARE\Vendor\Product if you expect a user priv process to be able to write to it. If you want to pass data to a service you might want to use some sort of IPC pipe to do so. Not sure what's available in Golang for this.

changing password with ansible on older systems

I need to change the password on a user for over a hundred system. I want to do this with ansible. Which is easy. However the user module on ansible requires a hashed password. I am concerned because there are a few older hosts which may not support newer types of hashing. I want to be able to programmatically identify what password hashing algorithms are available, and use the appropriate password hash to change. Or is there perhaps a better way to handle this whole sale.
I have considered the following:
echo username:password | chpasswd
and run that using the command module. That should use whatever the default algorithm is. Is there any cause for concern with this method?
In my mind, the ideal way would be to figure the supported hashes for each machine and then generate the proper hash for each machine.
The approach you list should work Just make sure you at "no_log: yes" to your task to ensure the password doesn't end up in the log file.
With either approach you're going to need have a way of getting the password(s) into ansible to use with the user module. Not sure if the passwords will be in a CSV file, yaml file or some other format. You could consider using vault to lock things down a bit more.

How do I manage secure files using a public babushka dep?

I want to share my babushka deps in much the same way as The Conversation do: https://github.com/conversation/babushka-deps
However, I manage SSL certificates and SSH keys using chef. Right now those files are directly in my chef config, but as I'd like to share my babushka config I can't put them there.
Is there a good way in babushka to deal with secure, outside-of-repo files?
This is something I'm working on at the moment. There's no built-in way, but it can be accomplished with a little bit of scripting.
If you're running the deps on a remote system, say from a shell script, then I'd add a command to the script to first rsync the private data into place:
rsync -taP private/ user#host:~/private/
ssh user#host 'babushka "server configured"'
That's the simplest case, but it quickly gets messy. Instead, I'm doing this sort of thing with babushka itself, in order to describe the whole process in terms of deps.
I have a dep with a couple of small helper methods for installing babushka on a remote machine, and then running arbitrary deps on it. This allows you to write local deps that depend on the results of remote runs, effectively nesting babushka within itself.
It's not quite general enough to be merged into core yet (and it's in need of a refactor), but it works well. Here it is if you'd like to give it a go in the meantime:
https://github.com/conversation/babushka-deps/blob/master/provision.rb#L123-131
Using this method, you can pass arguments to each remote run. That makes it easy to supply private data, e.g. your private key, or an SSL cert for setting up your webserver, etc.
(Note though that argument values are logged to ~/.babushka/logs/dep-name on the local and remote boxes, so 'private' assumes that the relevant user accounts on both are trusted.)

How to use ruby to access and write contents of Azure blobs using Secure Access Signatures?

I have several Azure Shared Access Signatures I need to access, list the blobs, and then export the contents. I am hoping I could just write a simple ruby script and run it on Mac.
Can someone share sample code? It's basically 'GET" to a URL with a signature, which I think from the command terminal I could use curl, but wasn't sure how to do it using Ruby to make it easier to loop through and maybe extend it later.
I'd be open to a bash script as well. Thanks.
A quick check on google returned https://github.com/johnnyhalife/waz-storage. Can you check this gem.

Resources