How to unlock Gnome Keyring from Python running on a Cron Job?

3.5k views Asked by At

I'm hooking a Python script up to run with cron (on Ubuntu 12.04), but authentication is not working.

The cron script accesses a couple services, and has to provide credentials. Storing those credentials with keyring is easy as can be, except that when the cron job actually runs, the credentials can't be retrieved. The script fails out every time.

As nearly as I can tell, this has something to do with the environment cron runs in. I tracked down a set of posts which suggest that the key is having the script export DBUS_SESSION_BUS_ADDRESS. All well and good, I can get that address and, export it, and source it from Python fairly easily. But it simply generates a new error: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11. Setting DISPLAY=:0 has no effect.

So, has anybody figured out how to unlock gnome-keyring from Python running on a Cron job on Ubuntu 12.04?

4

There are 4 answers

0
Xiankai Pang On

A few years late here. But for those who encounter the same problem, I just found a solution in Come and Tech it. Basically one need to add the following code at the beginning of the python script

import os
os.environ['DBUS_SESSION_BUS_ADDRESS'] = 'unix:path=/run/user/USERID/bus'
os.environ['DISPLAY'] = ':0'

and then the keyring can be accessed correctly. The value of 'USERID' can be obtained by the 'id' command in shell.

0
savenergy On

Adding:

PID=$(pgrep -u <replace with target userid> bash | head -n 1)
DBUS="$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/"$PID"/environ | sed 's/DBUS_SESSION_BUS_ADDRESS=//' )"
export DBUS_SESSION_BUS_ADDRESS=$DBUS

at the beginning of the script listed in the crontab worked for me. I still needed to unlock the keyring interactively once after a boot, but reboots are not frequent so it works ok.

(from https://forum.duplicacy.com/t/cron-job-failed-to-get-value-from-keyring/1238/3)

so the full script run by cron would be:

#! /usr/bin/bash

PID=$(pgrep -u <replace with target userid> bash | head -n 1)
DBUS="$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/"$PID"/environ | sed 's/DBUS_SESSION_BUS_ADDRESS=//' )"
export DBUS_SESSION_BUS_ADDRESS=$DBUS

/home/user/miniconda/conda run -n myenv python myscript.py

using an environment from conda. Or change the python invocation to however you set up python to be run.

0
user2849906 On

Install keychain:

sudo apt-get install keychain

Put it in your $HOME/.bash_profile :

if [ -z "$SSH_AUTH_SOCK" ] ; then
  eval `ssh-agent -s`
fi
eval `keychain --eval id_rsa`

It will ask your password at the first login, and will store your credentials until next reboot.

Insert it at the beginning of your cron script:

source $HOME/.keychain/${HOSTNAME}-sh

If you use other language such as python, call it from a wrapper script.

It works for me, I hope it helps you too.

3
David Eads On

I'm sorry to say I don't have the answer, but I think I know a bit of what's going on based on an issue I'm dealing with. I'm trying to get a web application and cron script to use some code that stashes an oauth token for Google's API into a keyring using python-keyring.

No matter what I do, something about the environment the web app and cron job runs in requires manual intervention to unlock the keyring. That's quite impossible when your code is running in a non-interactive session. The problem persists when trying some tricks suggested in my research, like giving the process owner a login password that matches the keyring password and setting the keyring password to an empty string.

I will almost guarantee that your error stems from Gnome-Keyring trying to fire up an interactive (graphical) prompt and bombing because you can't do that from cron.