mirror of
https://github.com/openSUSE/osc.git
synced 2025-01-27 15:06:15 +01:00
osc can now store credentials in Gnome keyring if it is available (bnc#460540)
This commit is contained in:
parent
72532fb016
commit
7074362e90
1
NEWS
1
NEWS
@ -12,6 +12,7 @@
|
|||||||
- osc rlog now works with srcmd5 also
|
- 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)
|
- 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 now includes automatically generated man page
|
||||||
|
- osc can now store credentials in Gnome keyring if it is available
|
||||||
|
|
||||||
0.117:
|
0.117:
|
||||||
- support checkout of single package via "osc co PACKAGE" when local dir is project
|
- support checkout of single package via "osc co PACKAGE" when local dir is project
|
||||||
|
9
README
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).
|
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:
|
USAGE EXAMPLES:
|
||||||
(online at http://en.opensuse.org/Build_Service/CLI )
|
(online at http://en.opensuse.org/Build_Service/CLI )
|
||||||
|
@ -88,6 +88,8 @@ class Osc(cmdln.Cmdln):
|
|||||||
optparser.add_option('-c', '--config', dest='conffile',
|
optparser.add_option('-c', '--config', dest='conffile',
|
||||||
metavar='FILE',
|
metavar='FILE',
|
||||||
help='specify alternate configuration file')
|
help='specify alternate configuration file')
|
||||||
|
optparser.add_option('--no-gnome-keyring', action='store_true',
|
||||||
|
help='disable usage of GNOME Keyring')
|
||||||
return optparser
|
return optparser
|
||||||
|
|
||||||
|
|
||||||
@ -99,7 +101,8 @@ class Osc(cmdln.Cmdln):
|
|||||||
override_debug = self.options.debug,
|
override_debug = self.options.debug,
|
||||||
override_http_debug = self.options.http_debug,
|
override_http_debug = self.options.http_debug,
|
||||||
override_traceback = self.options.traceback,
|
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:
|
except oscerr.NoConfigfile, e:
|
||||||
print >>sys.stderr, e.msg
|
print >>sys.stderr, e.msg
|
||||||
print >>sys.stderr, 'Creating osc configuration file %s ...' % e.file
|
print >>sys.stderr, 'Creating osc configuration file %s ...' % e.file
|
||||||
@ -118,13 +121,7 @@ class Osc(cmdln.Cmdln):
|
|||||||
import getpass
|
import getpass
|
||||||
user = raw_input('Username: ')
|
user = raw_input('Username: ')
|
||||||
passwd = getpass.getpass()
|
passwd = getpass.getpass()
|
||||||
cp = conf.get_configParser()
|
conf.add_section(e.file, e.url, user, passwd)
|
||||||
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()
|
|
||||||
if try_again: self.postoptparse(try_again = False)
|
if try_again: self.postoptparse(try_again = False)
|
||||||
|
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
|
84
osc/conf.py
84
osc/conf.py
@ -32,6 +32,14 @@ The configuration dictionary could look like this:
|
|||||||
import OscConfigParser
|
import OscConfigParser
|
||||||
from osc import oscerr
|
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
|
# being global to this module, this dict can be accessed from outside
|
||||||
# it will hold the parsed configuration
|
# it will hold the parsed configuration
|
||||||
config = { }
|
config = { }
|
||||||
@ -54,6 +62,7 @@ DEFAULTS = { 'apiurl': 'https://api.opensuse.org',
|
|||||||
'http_debug': '0',
|
'http_debug': '0',
|
||||||
'traceback': '0',
|
'traceback': '0',
|
||||||
'post_mortem': '0',
|
'post_mortem': '0',
|
||||||
|
'gnome_keyring': '1',
|
||||||
'cookiejar': '~/.osc_cookiejar',
|
'cookiejar': '~/.osc_cookiejar',
|
||||||
# enable project tracking by default
|
# enable project tracking by default
|
||||||
'do_package_tracking': '1',
|
'do_package_tracking': '1',
|
||||||
@ -104,6 +113,9 @@ apiurl = %(apiurl)s
|
|||||||
# print call traces in case of errors
|
# print call traces in case of errors
|
||||||
#traceback = 1
|
#traceback = 1
|
||||||
|
|
||||||
|
# use GNOME keyring for credentials if available
|
||||||
|
#gnome_keyring = 0
|
||||||
|
|
||||||
[%(apiurl)s]
|
[%(apiurl)s]
|
||||||
user = %(user)s
|
user = %(user)s
|
||||||
pass = %(pass)s
|
pass = %(pass)s
|
||||||
@ -114,6 +126,8 @@ pass = %(pass)s
|
|||||||
# additional headers to pass to a request, e.g. for special authentication
|
# additional headers to pass to a request, e.g. for special authentication
|
||||||
#http_headers = Host: foofoobar,
|
#http_headers = Host: foofoobar,
|
||||||
# User: mumblegack
|
# 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
|
conf_template = custom_template or new_conf_template
|
||||||
config = DEFAULTS.copy()
|
config = DEFAULTS.copy()
|
||||||
config.update(entries)
|
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)
|
sio = StringIO.StringIO(conf_template.strip() % config)
|
||||||
cp = OscConfigParser.OscConfigParser(DEFAULTS)
|
cp = OscConfigParser.OscConfigParser(DEFAULTS)
|
||||||
cp.readfp(sio)
|
cp.readfp(sio)
|
||||||
@ -279,13 +303,41 @@ def write_initial_config(conffile, entries, custom_template = ''):
|
|||||||
finally:
|
finally:
|
||||||
if file: file.close()
|
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,
|
def get_config(override_conffile = None,
|
||||||
override_apiurl = None,
|
override_apiurl = None,
|
||||||
override_debug = None,
|
override_debug = None,
|
||||||
override_http_debug = None,
|
override_http_debug = None,
|
||||||
override_traceback = None,
|
override_traceback = None,
|
||||||
override_post_mortem = None):
|
override_post_mortem = None,
|
||||||
|
override_no_gnome_keyring = None):
|
||||||
"""do the actual work (see module documentation)"""
|
"""do the actual work (see module documentation)"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -346,16 +398,38 @@ def get_config(override_conffile = None,
|
|||||||
# the following regexp does _not_ support quoted commas within the value.
|
# the following regexp does _not_ support quoted commas within the value.
|
||||||
http_header_regexp = re.compile(r"\s*(.*?)\s*:\s*(.*?)\s*(?:,\s*|\Z)")
|
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 = {}
|
aliases = {}
|
||||||
for url in [ x for x in cp.sections() if x != 'general' ]:
|
for url in [ x for x in cp.sections() if x != 'general' ]:
|
||||||
# backward compatiblity
|
# backward compatiblity
|
||||||
scheme, host = \
|
scheme, host = \
|
||||||
parse_apisrv_url(config.get('scheme', 'https'), url)
|
parse_apisrv_url(config.get('scheme', 'https'), url)
|
||||||
apiurl = urljoin(scheme, host)
|
apiurl = urljoin(scheme, host)
|
||||||
#FIXME: this could actually be the ideal spot to take defaults
|
user = None
|
||||||
#from the general section.
|
# Read from gnome keyring if available
|
||||||
user = cp.get(url, 'user')
|
if config['gnome_keyring'] and GNOME_KEYRING:
|
||||||
password = cp.get(url, 'pass')
|
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 = ''
|
email = ''
|
||||||
if cp.has_option(url, 'email'):
|
if cp.has_option(url, 'email'):
|
||||||
email = cp.get(url, 'email')
|
email = cp.get(url, 'email')
|
||||||
|
Loading…
Reference in New Issue
Block a user