Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

osc can now store credentials in Gnome keyring if it is available (bn…

…c#460540)
  • Loading branch information...
commit 7074362e90afb0ed6eac7fdd94537e504b9a441b 1 parent 72532fb
@nijel nijel authored
Showing with 94 additions and 13 deletions.
  1. +1 −0  NEWS
  2. +9 −0 README
  3. +5 −8 osc/commandline.py
  4. +79 −5 osc/conf.py
View
1  NEWS
@@ -12,6 +12,7 @@
- osc rlog now works with srcmd5 also
- plugins now should be placed in /usr/lib/osc-plugins to match FHS (the /var path is still supported though)
- osc now includes automatically generated man page
+- osc can now store credentials in Gnome keyring if it is available
0.117:
- support checkout of single package via "osc co PACKAGE" when local dir is project
View
9 README
@@ -115,6 +115,15 @@ described above. So basically just adjust all apiurl sections (it might be the
case that some sections already have the correct format).
+KEYRING USAGE
+
+Osc now can store passwords in Gnome keyring instead of ~/.oscrc. To use it,
+you need python-gnomekeyring and keyring daemon running.
+
+If you want to switch to using Gnome keyring you need to delete apiurl section
+from ~/.oscrc and you will be asked for credentials again, which will be then
+stored in Gnome keyring.
+
USAGE EXAMPLES:
(online at http://en.opensuse.org/Build_Service/CLI )
View
13 osc/commandline.py
@@ -88,6 +88,8 @@ def get_optparser(self):
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
@@ -99,7 +101,8 @@ def postoptparse(self, try_again = True):
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
@@ -118,13 +121,7 @@ def postoptparse(self, try_again = True):
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
View
84 osc/conf.py
@@ -32,6 +32,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 = { }
@@ -54,6 +62,7 @@
'http_debug': '0',
'traceback': '0',
'post_mortem': '0',
+ 'gnome_keyring': '1',
'cookiejar': '~/.osc_cookiejar',
# enable project tracking by default
'do_package_tracking': '1',
@@ -104,6 +113,9 @@
# print call traces in case of errors
#traceback = 1
+# use GNOME keyring for credentials if available
+#gnome_keyring = 0
+
[%(apiurl)s]
user = %(user)s
pass = %(pass)s
@@ -114,6 +126,8 @@
# 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
"""
@@ -261,6 +275,16 @@ def write_initial_config(conffile, entries, custom_template = ''):
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)
@@ -279,13 +303,41 @@ def write_initial_config(conffile, entries, custom_template = ''):
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_apiurl = 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
@@ -346,16 +398,38 @@ def get_config(override_conffile = None,
# 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
+
aliases = {}
for url in [ x for x in cp.sections() if x != 'general' ]:
# backward compatiblity
scheme, host = \
parse_apisrv_url(config.get('scheme', 'https'), url)
apiurl = urljoin(scheme, host)
- #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 = scheme,
+ 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
email = ''
if cp.has_option(url, 'email'):
email = cp.get(url, 'email')
Please sign in to comment.
Something went wrong with that request. Please try again.