Mailinglist Archive: opensuse-buildservice (233 mails)

< Previous Next >
Re: [opensuse-buildservice] Using keyring for storing passwords
  • From: Michal Čihař <michal@xxxxxxxxx>
  • Date: Thu, 4 Dec 2008 15:04:25 +0100
  • Message-id: <20081204150425.2180a4a6@xxxxxxxxxxxxxxxxx>
Hi

Dne Thu, 4 Dec 2008 13:39:32 +0100
"Jan-Simon Möller" <dl9pf@xxxxxx> napsal(a):

Am Thursday 04 December 2008 13:15:54 schrieb Michal Čihař:
Hi

What is wrong on optional dependency? If python-gnomekeyring is not
found or is not working, osc still behaves same as without patch. Maybe
there could be also configuration option to disable usage of keyring...

Add a config-option to disable it if needed. Then its imho ready for
inclusion.

Okay, added config option and command line switch to disable it.

Next steps would be:

a) what about kwalletmanager ?

I have no idea how to use it, but in case it has also Python API, it
can be integrated also quite easily.

b) what about password-encryption for osc itself ?

That would ask you for password on every operation, what is not really
comfortable.

--
Michal Čihař | http://cihar.com | http://blog.cihar.com
Index: osc/conf.py
===================================================================
--- osc/conf.py (revision 5802)
+++ osc/conf.py (working copy)
@@ -37,6 +37,14 @@
import OscConfigParser
from osc import oscerr

+try:
+ import gobject
+ gobject.set_application_name('osc')
+ import gnomekeyring
+ GNOME_KEYRING = gnomekeyring.is_available()
+except:
+ GNOME_KEYRING = False
+
# being global to this module, this dict can be accessed from outside
# it will hold the parsed configuration
config = { }
@@ -62,6 +70,7 @@
'http_debug': '0',
'traceback': '0',
'post_mortem': '0',
+ 'gnome_keyring': '1',
'cookiejar': '~/.osc_cookiejar',
# disable project tracking by default
'do_package_tracking': '0',
@@ -111,12 +120,17 @@
# print call traces in case of errors
#traceback = 1

+# use GNOME keyring for credentials if available
+#gnome_keyring = 0
+
[%(apisrv)s]
user = %(user)s
pass = %(pass)s
# additional headers to pass to a request, e.g. for special authentication
#http_headers = Host: foofoobar,
# User: mumblegack
+# Force using of keyring for this API
+#keyring = 1
"""


@@ -252,6 +266,16 @@
conf_template = custom_template or new_conf_template
config = DEFAULTS.copy()
config.update(entries)
+ if config['gnome_keyring'] and GNOME_KEYRING:
+ protocol, host = \
+ parse_apisrv_url(None, config['apisrv'])
+ gnomekeyring.set_network_password_sync(
+ user = config['user'],
+ password = config['pass'],
+ protocol = protocol,
+ server = host)
+ config['user'] = ''
+ config['pass'] = ''
sio = StringIO.StringIO(conf_template.strip() % config)
cp = OscConfigParser.OscConfigParser(DEFAULTS)
cp.readfp(sio)
@@ -270,13 +294,41 @@
finally:
if file: file.close()

+def add_section(filename, url, user, passwd):
+ """
+ Add a section to config file for new api url.
+ """
+ global config
+ cp = get_configParser(filename)
+ try:
+ cp.add_section(url)
+ except OscConfigParser.ConfigParser.DuplicateSectionError:
+ # Section might have existed, but was empty
+ pass
+ if config['gnome_keyring'] and GNOME_KEYRING:
+ protocol, host = \
+ parse_apisrv_url(None, url)
+ gnomekeyring.set_network_password_sync(
+ user = user,
+ password = passwd,
+ protocol = protocol,
+ server = host)
+ cp.set(url, 'keyring', '1')
+ else:
+ cp.set(url, 'user', user)
+ cp.set(url, 'pass', passwd)
+ file = open(filename, 'w')
+ cp.write(file, True)
+ if file: file.close()

+
def get_config(override_conffile = None,
override_apisrv = None,
override_debug = None,
override_http_debug = None,
override_traceback = None,
- override_post_mortem = None):
+ override_post_mortem = None,
+ override_no_gnome_keyring = None):
"""do the actual work (see module documentation)"""
import os
import sys
@@ -332,13 +384,35 @@
# the following regexp does _not_ support quoted commas within the value.
http_header_regexp = re.compile(r"\s*(.*?)\s*:\s*(.*?)\s*(?:,\s*|\Z)")

+ # override values which we were called with
+ # This needs to be done before processing API sections as it might be
already used there
+ if override_no_gnome_keyring:
+ config['gnome_keyring'] = False
+
for url in [ x for x in cp.sections() if x != 'general' ]:
- dummy, host = \
+ protocol, host = \
parse_apisrv_url(config['scheme'], url)
- #FIXME: this could actually be the ideal spot to take defaults
- #from the general section.
- user = cp.get(url, 'user')
- password = cp.get(url, 'pass')
+ user = None
+ # Read from gnome keyring if available
+ if config['gnome_keyring'] and GNOME_KEYRING:
+ try:
+ gk_data = gnomekeyring.find_network_password_sync(
+ protocol = protocol,
+ server = host)
+ password = gk_data[0]['password']
+ user = gk_data[0]['user']
+ except gnomekeyring.NoMatchError:
+ # Fallback to file based auth.
+ pass
+ # Read credentials from config
+ if user is None:
+ #FIXME: this could actually be the ideal spot to take defaults
+ #from the general section.
+ user = cp.get(url, 'user')
+ password = cp.get(url, 'pass')
+ if cp.has_option(url, 'keyring') and cp.get(url, 'keyring'):
+ # This APIURL was configured to use keyring by
+ continue

if cp.has_option(url, 'http_headers'):
http_headers = cp.get(url, 'http_headers')
Index: osc/commandline.py
===================================================================
--- osc/commandline.py (revision 5802)
+++ osc/commandline.py (working copy)
@@ -59,6 +59,8 @@
optparser.add_option('-c', '--config', dest='conffile',
metavar='FILE',
help='specify alternate configuration file')
+ optparser.add_option('--no-gnome-keyring', action='store_true',
+ help='disable usage of GNOME Keyring')
return optparser


@@ -70,7 +72,8 @@
override_debug = self.options.debug,
override_http_debug = self.options.http_debug,
override_traceback = self.options.traceback,
- override_post_mortem = self.options.post_mortem)
+ override_post_mortem = self.options.post_mortem,
+ override_no_gnome_keyring =
self.options.no_gnome_keyring)
except oscerr.NoConfigfile, e:
print >>sys.stderr, e.msg
print >>sys.stderr, 'Creating osc configuration file %s ...' %
e.file
@@ -87,13 +90,7 @@
import getpass
user = raw_input('Username: ')
passwd = getpass.getpass()
- cp = conf.get_configParser()
- cp.add_section(e.url)
- cp.set(e.url, 'user', user)
- cp.set(e.url, 'pass', passwd)
- file = open(e.file, 'w')
- cp.write(file, True)
- if file: file.close()
+ conf.add_section(e.file, e.url, user, passwd)
if try_again: self.postoptparse(try_again = False)

self.conf = conf
< Previous Next >