jaraco / keyring

MIT License
1.24k stars 152 forks source link

Proposal: add WSL backend via windows executable #622

Open AlexanderLanin opened 1 year ago

AlexanderLanin commented 1 year ago

Don't worry, this is not the 4th request to access windows APIs from Linux ;-) I want to pinch the following idea, and I'm also willing to give it a try myself if it's worthwhile.

In case python is running on WSL, we usually have quite some trouble installing/running any other reasonable backend. We also don't have (simple) access to windows APIs. However what we have is access to windows executables!

Now all we need is an executable which can access the credential store for us. Microsoft provides one (cmdkey), but for whatever reason it does not read passwords :(

For the sake of argument let's say we have python with pywin32 installed.

store test_pass:

/mnt/c/Users/lla2hi$ /mnt/c/Program\ Files\ \(x86\)/Python39-32/python.exe -c "import pywintypes; import win32cred; win32cred.CredWrite({'Type':win32cred.CRED_TYPE_GENERIC, 'TargetName':'test_service', 'UserName':'test_user', 'CredentialBlob':'test_pass', 'Comment':'Stored using python-keyring', 'Persist':win32cred.CRED_PERSIST_ENTERPRISE}, 0);"

retrieve test_pass:

/mnt/c/Program\ Files\ \(x86\)/Python39-32/python.exe -c "import win32cred; print(win32cred.CredRead(Type=win32cred.CRED_TYPE_GENERIC, TargetName='test_service')['Credential
Blob'].decode('utf-16'));"
test_pass

We can easily do that from our WSL python by starting a subprocess!

Maybe there is a better windows executable than python.exe with pywin32 installed... When I try the same with powershell it asks for a password. I do not understand yet why it's fine from python, but from powershell I need to authenticate.

jaraco commented 1 year ago

That all sounds reasonable. Usually, when it comes to providing backends, we recommend to first develop a plugin, and if a backend demonstrates broad usage, it might be incorporated as a built-in backend. See the readme for some guidance on creating such a backend, and of course feel free to ask questions. Of course, if you're just experimenting, feel free to just add another backend to keyring in your fork to test and experiment. The interfaces are fairly simple and intuitive, but let us know how we can help.

raayu83 commented 1 year ago

It should be possible to create a small CLI App using https://github.com/danieljoos/wincred . If it would then be made available with winget and integrated into the Windows Backend of Keyring, there would be an easy way to setup keyring in WSL.

Unfortunately I don't know Go, so I can't do the first part on my own.

Korijn commented 1 year ago

General note: You can hop to a Windows execution context at any time by calling a subprocess via cmd or powershell, e.g. calling cmd.exe /c <some-command> using subprocess.run in a WSL python process will interface with Windows.

On topic: One idea is to reuse keyring as the solution! Install keyring on Windows globally, and then call out to the Windows keyring from the WSL keyring keyring.exe <some-command>

You don't have to install it globally, but you obviously need to know the path to be able to communicate with the Windows keyring install <path-to-keyring.exe> <some-command>

Korijn commented 1 year ago

On topic: One idea is to reuse keyring as the solution! Install keyring on Windows globally, and then call out to the Windows keyring from the WSL keyring

I implemented and tested this idea successfully here: https://github.com/ClinicalGraphics/keycmd/blob/078b43e47e039aac371d76fe9cae3cd8c4451e72/keycmd/wsl.py

You just need to point it to a python executable on the host that has keyring installed by setting KEYRING_PROPERTY_PYTHON=C:\path\to\python.exe Activate this backend as usual: PYTHON_KEYRING_BACKEND=keycmd.wsl.WslHostKeyring

I'll make this available as a separate keyring plugin package later.

Korijn commented 1 year ago

Here it is: https://github.com/ClinicalGraphics/keyring-pybridge