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):
Okay, added config option and command line switch to disable it.
I have no idea how to use it, but in case it has also Python API, it
can be integrated also quite easily.
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
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 > |