jaraco / keyring

MIT License
1.26k stars 159 forks source link

keyring.get_keyring() throws an exception when executed by cron #620

Closed bascetta74 closed 1 year ago

bascetta74 commented 1 year ago

A call to keyring.get_keyring() in a python script gives no problem when the script is executed from the shell, but throws an exception when it is executed by cron.

The attached file test.zip includes a bash script that runs a python script (the bash scripts sets also the DISPLAY variable as the first exception thrown by get_keyring was related to a non correctly initialized DISPLAY variable). Running the bash script from the terminal gives, as expected, the following output:

keyring.backends.kwallet.DBusKeyring (priority: 4.9)

When the same script is run by cron, using the line

*/5 * * * * /home/bascetta/Documents/test.bash > /home/bascetta/Documents/test-res.txt

the following output is generated

Exception type : RuntimeError 
Exception message : /usr/bin/dbus-launch terminated abnormally without any error message
Stack trace : ['File : /home/bascetta/Documents/test-py.py , Line : 11, Func.Name : <module>, Message : print(keyring.get_keyring())', 'File : /usr/lib/python3/dist-packages/keyring/core.py , Line : 32, Func.Name : get_keyring, Message : init_backend()', 'File : /usr/lib/python3/dist-packages/keyring/core.py , Line : 83, Func.Name : init_backend, Message : set_keyring(_detect_backend(limit))', 'File : /usr/lib/python3/dist-packages/keyring/core.py , Line : 98, Func.Name : _detect_backend, Message : or load_config()', 'File : /usr/lib/python3/dist-packages/keyring/core.py , Line : 177, Func.Name : load_config, Message : return load_keyring(keyring_name)', 'File : /usr/lib/python3/dist-packages/keyring/core.py , Line : 136, Func.Name : load_keyring, Message : class_.priority', 'File : /usr/lib/python3/dist-packages/keyring/util/properties.py , Line : 24, Func.Name : __get__, Message : return self.fget.__get__(None, owner)()', 'File : /usr/lib/python3/dist-packages/keyring/backends/kwallet.py , Line : 48, Func.Name : priority, Message : raise RuntimeError(exc.get_dbus_message())']

Environment Ubuntu 22.04.1 (5.15.0-58-generic) Python 3.10.6 keyring 23.5.0

aryoda commented 1 year ago

When the same script is run by cron ...

Which crontab are you using? The user's or the system's (root)?

aryoda commented 1 year ago

I think this may be caused by the fact that cron does not use the same env vars as the user so that some required keyring env vars may be missing, e.g. DBUS_SESSION_BUS_ADDRESS).

See this issue and the real-life diff of the env vars of a job started via cron vs. as user:

https://github.com/bit-team/backintime/issues/1236#issuecomment-1337624042

bascetta74 commented 1 year ago

I'm using the user crontab. I also checked inserting a whoami in the bassh script run by crontab.


Da: aryoda @.> Inviato: lunedì 23 gennaio 2023 03:27 A: jaraco/keyring @.> Cc: Luca Bascetta @.>; Author @.> Oggetto: Re: [jaraco/keyring] keyring.get_keyring() throws an exception when executed by cron (Issue #620)

When the same script is run by cron ...

Which crontab are you using? The user's or the system's (root)?

— Reply to this email directly, view it on GitHubhttps://github.com/jaraco/keyring/issues/620#issuecomment-1399704698, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AK243X2DRLBF74AWJSEZ7HTWTXUCVANCNFSM6AAAAAAUC5N37E. You are receiving this because you authored the thread.Message ID: @.***>

bascetta74 commented 1 year ago

sThank you very much for your suggestion. My problem was with Backintime, and it was exactly what you mentioned, the DBUS_SESSION_BUS_ADDRESS variable is empty in the environment used by cron.

Adding this lines to the cron script

# Set DISPLAY variable
DISPLAY=$(w -h $USER | awk '$2 ~ /:[0-9.]*/{print $2}')
export DISPLAY

# Set DBUS_SESSION_BUS_ADDRESS variable
pid_gnome=$(pgrep gnome-session|head -1)
DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/${pid_gnome}/environ| cut -d= -f2- | tr -d '\0\n')
export DBUS_SESSION_BUS_ADDRESS

solves the issue.


Da: aryoda @.> Inviato: lunedì 23 gennaio 2023 03:42 A: jaraco/keyring @.> Cc: Luca Bascetta @.>; Author @.> Oggetto: Re: [jaraco/keyring] keyring.get_keyring() throws an exception when executed by cron (Issue #620)

I think this may be caused by the fact that cron does not use the same env vars as the user so that some required keyring env vars may be missing, e.g. DBUS_SESSION_BUS_ADDRESS).

See this issue and the real-life diff of the env vars of a job started via cron vs. as user:

bit-team/backintime#1236 (comment)https://github.com/bit-team/backintime/issues/1236#issuecomment-1337624042

— Reply to this email directly, view it on GitHubhttps://github.com/jaraco/keyring/issues/620#issuecomment-1399715051, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AK243X2NAPTJCAYBOGC44F3WTXV23ANCNFSM6AAAAAAUC5N37E. You are receiving this because you authored the thread.Message ID: @.***>

aryoda commented 1 year ago

THX for testing and your feed-back.

Requiring the above script lines to export DBUS_SESSION_BUS_ADDRESS raises the question if backintime via cron does work without these lines.

On my TODO list now (but with low prio ATM due to high workload)...

aryoda commented 1 year ago

@jaraco Would it be worth to add a FAQ for keyring with cron and mention this issue here as a solution?

jaraco commented 1 year ago

That sounds like a good idea. Feel free to draft a PR.

jheasly commented 5 months ago

Using a user cron I was able to grant it keyring.get_password() access by making a copy of the password from the user login Keychain (using the Keychain Access app) and putting it on the System Keychain. I also had to open the Access Control of the copied password item and add the python from the virtual environment that was running the Python script to the "Always allow access by these applications:" list. Now the user cron works like a champ.

Screenshot 2024-05-31 at 12 41 25 PM