Skip to content

Commit 3449858

Browse files
author
Matthew Davis
committed
Allow creation and unlock of SecretService keyring on headless systems.
Corrected issues related to Style guide for Python Correct PEP8 over indentation
1 parent f4626dd commit 3449858

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

osc/credentials.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,91 @@ def create(self, cp):
164164

165165

166166
class KeyringCredentialsManager(AbstractCredentialsManager):
167+
def _start_SecretService_Keyring(self):
168+
import os
169+
import subprocess
170+
171+
keyring_daemon = '/usr/bin/gnome-keyring-daemon'
172+
if not os.path.exists(keyring_daemon):
173+
# Gnome Keyring Daemon in not installed.
174+
# return quickly since there is nothing to do.
175+
return
176+
177+
# Starts and unlock GNOME keyring when running headless.
178+
179+
if 'DISPLAY' in os.environ:
180+
# Looks like we have desktop session
181+
# Continue to the normal desktop unlock procedures.
182+
return
183+
if 'DBUS_SESSION_BUS_ADDRESS' in os.environ:
184+
# Ensure DBUS has launced for headless GNOME_KEYRING.
185+
pass
186+
else:
187+
raise SystemExit("""
188+
The DBUS_SESSION_BUS_ADDRESS environment variable is not set which
189+
probably means that DBUS is not running.
190+
""")
191+
192+
# Ensure the GNOME_KEYRING is started.
193+
if 'GNOME_KEYRING_CONTORL' in os.environ:
194+
if not os.path.exists(os.environ.get('GNOME_KEYRING_CONTROL')):
195+
# Make the uses .local directory. Otherwise
196+
# initial keyring creation will fail.
197+
if not os.path.exists(os.path.expanduser('~/.local')):
198+
os.makedirs(os.path.expanduser('~/.local'), mode=0o700)
199+
# GNOME Keyring daemon is not running, so we start it here.
200+
process = subprocess.Popen([keyring_daemon,
201+
'--start', '--components=secrets'],
202+
stdin=subprocess.DEVNULL,
203+
stdout=subprocess.DEVNULL,
204+
stderr=subprocess.DEVNULL)
205+
process.communicate(timeout=5)
206+
try:
207+
import secretstorage
208+
dbus = secretstorage.dbus_init()
209+
collection = secretstorage.get_default_collection(dbus)
210+
if collection.is_locked():
211+
pass
212+
else:
213+
return
214+
except BaseException:
215+
collection = None
216+
self._unlock_SecretService_Keyring(keyring_daemon, collection)
217+
218+
def _unlock_SecretService_Keyring(self, keyring_daemon, collection):
219+
import os
220+
import subprocess
221+
keyringf = os.path.expanduser('~/.local/share/keyrings/login.keyring')
222+
keystore = os.path.expanduser('~/.local/share/keyrings/user.keystore')
223+
if not os.path.exists(keyringf) and not os.path.exists(keystore):
224+
prompt = 'New keyring password: '
225+
else:
226+
prompt = 'Keyring password: '
227+
228+
password = getpass.getpass(prompt=prompt)
229+
password = (password + '\n').encode('UTF-8')
230+
process = subprocess.Popen([keyring_daemon,
231+
'--unlock', '--replace',
232+
'--components=secrets'],
233+
stdin=subprocess.PIPE,
234+
stdout=subprocess.DEVNULL,
235+
stderr=subprocess.DEVNULL)
236+
process.communicate(input=password, timeout=5)
237+
if collection is None:
238+
import secretstorage
239+
dbus = secretstorage.dbus_init()
240+
collection = secretstorage.get_default_collection(dbus)
241+
if collection.is_locked():
242+
raise SystemExit('Unable to unlock keyring.')
243+
167244
def _process_options(self, options):
168245
if options is None:
169246
raise RuntimeError('options may not be None')
170247
self._backend_cls_name = options
171248

172249
def _load_backend(self):
250+
if self._backend_cls_name == 'keyring.backends.SecretService.Keyring':
251+
self._start_SecretService_Keyring()
173252
keyring_backend = keyring.core.load_keyring(self._backend_cls_name)
174253
keyring.set_keyring(keyring_backend)
175254

0 commit comments

Comments
 (0)