def get_config(override_conffile=None, override_apiurl=None, override_debug=None, override_http_debug=None, override_http_full_debug=None, override_traceback=None, override_post_mortem=None, override_no_keyring=None, override_no_gnome_keyring=None, override_verbose=None): """do the actual work (see module documentation)""" global config conffile = override_conffile or os.environ.get('OSC_CONFIG', '~/.oscrc') conffile = os.path.expanduser(conffile) if not os.path.exists(conffile): raise oscerr.NoConfigfile(conffile, \ account_not_configured_text % conffile) # okay, we made sure that .oscrc exists # make sure it is not world readable, it may contain a password. os.chmod(conffile, 0600) cp = get_configParser(conffile) if not cp.has_section('general'): # FIXME: it might be sufficient to just assume defaults? msg = config_incomplete_text % conffile msg += new_conf_template % DEFAULTS raise oscerr.ConfigError(msg, conffile) config = dict(cp.items('general', raw=1)) config['conffile'] = conffile for i in boolean_opts: try: config[i] = cp.getboolean('general', i) except ValueError, e: raise oscerr.ConfigError( 'cannot parse \'%s\' setting: ' % i + str(e), conffile)
def get_config(override_conffile=None, override_apiurl=None, override_debug=None, override_http_debug=None, override_http_full_debug=None, override_traceback=None, override_post_mortem=None, override_no_keyring=None, override_no_gnome_keyring=None, override_verbose=None): """do the actual work (see module documentation)""" global config conffile = override_conffile or os.environ.get('OSC_CONFIG', '~/.oscrc') conffile = os.path.expanduser(conffile) if not os.path.exists(conffile): raise oscerr.NoConfigfile(conffile, \ account_not_configured_text % conffile) # okay, we made sure that .oscrc exists # make sure it is not world readable, it may contain a password. os.chmod(conffile, 0o600) cp = get_configParser(conffile) if not cp.has_section('general'): # FIXME: it might be sufficient to just assume defaults? msg = config_incomplete_text % conffile msg += new_conf_template % DEFAULTS raise oscerr.ConfigError(msg, conffile) config = dict(cp.items('general', raw=1)) config['conffile'] = conffile for i in boolean_opts: try: config[i] = cp.getboolean('general', i) except ValueError as e: raise oscerr.ConfigError( 'cannot parse \'%s\' setting: ' % i + str(e), conffile) config['packagecachedir'] = os.path.expanduser(config['packagecachedir']) config['exclude_glob'] = config['exclude_glob'].split() re_clist = re.compile('[, ]+') config['extra-pkgs'] = [ i.strip() for i in re_clist.split(config['extra-pkgs'].strip()) if i ] # collect the usernames, passwords and additional options for each api host api_host_options = {} # Regexp to split extra http headers into a dictionary # the text to be matched looks essentially looks this: # "Attribute1: value1, Attribute2: value2, ..." # there may be arbitray leading and intermitting whitespace. # 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_keyring: config['use_keyring'] = False 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, path = parse_apisrv_url(config.get('scheme', 'https'), url) apiurl = urljoin(scheme, host, path) user = None password = None if config['use_keyring'] and GENERIC_KEYRING: try: # Read from keyring lib if available user = cp.get(url, 'user', raw=True) password = str(keyring.get_password(host, user)) except: # Fallback to file based auth. pass elif config['gnome_keyring'] and GNOME_KEYRING: # Read from gnome keyring if available try: gk_data = gnomekeyring.find_network_password_sync( protocol=scheme, server=host, object=path) if not 'user' in gk_data[0]: raise oscerr.ConfigError('no user found in keyring', conffile) user = gk_data[0]['user'] if 'password' in gk_data[0]: password = str(gk_data[0]['password']) else: # this is most likely an error print('warning: no password found in keyring', file=sys.stderr) except gnomekeyring.NoMatchError: # Fallback to file based auth. pass if not user is None and len(user) == 0: user = None print('Warning: blank user in the keyring for the ' \ 'apiurl %s.\nPlease fix your keyring entry.', file=sys.stderr) if user is not None and password is None: err = ( 'no password defined for "%s".\nPlease fix your keyring ' 'entry or gnome-keyring setup.\nAssuming an empty password.' % url) print(err, file=sys.stderr) password = '' # 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', raw=True) # need to set raw to prevent '%' expansion password = cp.get(url, 'pass', raw=True) # especially on password! try: passwordx = passx_decode(cp.get( url, 'passx', raw=True)) # especially on password! except: passwordx = '' if password == None or password == 'your_password': password = '' if user is None or user == '': raise oscerr.ConfigError( 'user is blank for %s, please delete or complete the "user=" entry in %s.' % (apiurl, config['conffile']), config['conffile']) if config['plaintext_passwd'] and passwordx or not config[ 'plaintext_passwd'] and password: if config['plaintext_passwd']: if password != passwordx: print('%s: rewriting from encoded pass to plain pass' % url, file=sys.stderr) add_section(conffile, url, user, passwordx) password = passwordx else: if password != passwordx: print('%s: rewriting from plain pass to encoded pass' % url, file=sys.stderr) add_section(conffile, url, user, password) if not config['plaintext_passwd']: password = passwordx if cp.has_option(url, 'http_headers'): http_headers = cp.get(url, 'http_headers') http_headers = http_header_regexp.findall(http_headers) else: http_headers = [] if cp.has_option(url, 'aliases'): for i in cp.get(url, 'aliases').split(','): key = i.strip() if key == '': continue if key in aliases: msg = 'duplicate alias entry: \'%s\' is already used for another apiurl' % key raise oscerr.ConfigError(msg, conffile) aliases[key] = url api_host_options[apiurl] = { 'user': user, 'pass': password, 'http_headers': http_headers } optional = ('email', 'sslcertck', 'cafile', 'capath') for key in optional: if cp.has_option(url, key): if key == 'sslcertck': api_host_options[apiurl][key] = cp.getboolean(url, key) else: api_host_options[apiurl][key] = cp.get(url, key) if cp.has_option(url, 'build-root', proper=True): api_host_options[apiurl]['build-root'] = cp.get(url, 'build-root', raw=True) if not 'sslcertck' in api_host_options[apiurl]: api_host_options[apiurl]['sslcertck'] = True if scheme == 'http': api_host_options[apiurl]['sslcertck'] = False if cp.has_option(url, 'trusted_prj'): api_host_options[apiurl]['trusted_prj'] = cp.get( url, 'trusted_prj').split(' ') else: api_host_options[apiurl]['trusted_prj'] = [] # add the auth data we collected to the config dict config['api_host_options'] = api_host_options config['apiurl_aliases'] = aliases apiurl = aliases.get(config['apiurl'], config['apiurl']) config['apiurl'] = urljoin(*parse_apisrv_url(None, apiurl)) # backward compatibility if 'apisrv' in config: apisrv = config['apisrv'].lstrip('http://') apisrv = apisrv.lstrip('https://') scheme = config.get('scheme', 'https') config['apiurl'] = urljoin(scheme, apisrv) if 'apisrc' in config or 'scheme' in config: print('Warning: Use of the \'scheme\' or \'apisrv\' in ~/.oscrc is deprecated!\n' \ 'Warning: See README for migration details.', file=sys.stderr) if 'build_platform' in config: print( 'Warning: Use of \'build_platform\' config option is deprecated! (use \'build_repository\' instead)', file=sys.stderr) config['build_repository'] = config['build_platform'] config['verbose'] = int(config['verbose']) # override values which we were called with if override_verbose: config['verbose'] = override_verbose + 1 if override_debug: config['debug'] = override_debug if override_http_debug: config['http_debug'] = override_http_debug if override_http_full_debug: config['http_debug'] = override_http_full_debug or config['http_debug'] config['http_full_debug'] = override_http_full_debug if override_traceback: config['traceback'] = override_traceback if override_post_mortem: config['post_mortem'] = override_post_mortem if override_apiurl: apiurl = aliases.get(override_apiurl, override_apiurl) # check if apiurl is a valid url config['apiurl'] = urljoin(*parse_apisrv_url(None, apiurl)) # XXX unless config['user'] goes away (and is replaced with a handy function, or # config becomes an object, even better), set the global 'user' here as well, # provided that there _are_ credentials for the chosen apiurl: try: config['user'] = get_apiurl_usr(config['apiurl']) except oscerr.ConfigMissingApiurl as e: e.msg = config_missing_apiurl_text % config['apiurl'] e.file = conffile raise e # finally, initialize urllib2 for to use the credentials for Basic Authentication init_basicauth(config)
def get_config(override_conffile=None, override_apiurl=None, override_debug=None, override_http_debug=None, override_http_full_debug=None, override_traceback=None, override_post_mortem=None, override_no_keyring=None, override_no_gnome_keyring=None, override_verbose=None): """do the actual work (see module documentation)""" global config if not override_conffile: conffile = identify_conf() else: conffile = override_conffile conffile = os.path.expanduser(conffile) if not os.path.exists(conffile): raise oscerr.NoConfigfile(conffile, \ account_not_configured_text % conffile) # okay, we made sure that oscrc exists # make sure it is not world readable, it may contain a password. os.chmod(conffile, 0o600) cp = get_configParser(conffile) if not cp.has_section('general'): # FIXME: it might be sufficient to just assume defaults? msg = config_incomplete_text % conffile msg += new_conf_template % DEFAULTS raise oscerr.ConfigError(msg, conffile) config = dict(cp.items('general', raw=1)) config['conffile'] = conffile typed_opts = ((boolean_opts, cp.getboolean), (integer_opts, cp.getint)) for opts, meth in typed_opts: for opt in opts: try: config[opt] = meth('general', opt) except ValueError as e: msg = 'cannot parse \'%s\' setting: %s' % (opt, str(e)) raise oscerr.ConfigError(msg, conffile) config['packagecachedir'] = os.path.expanduser(config['packagecachedir']) config['exclude_glob'] = config['exclude_glob'].split() re_clist = re.compile('[, ]+') config['extra-pkgs'] = [ i.strip() for i in re_clist.split(config['extra-pkgs'].strip()) if i ] # collect the usernames, passwords and additional options for each api host api_host_options = {} # Regexp to split extra http headers into a dictionary # the text to be matched looks essentially looks this: # "Attribute1: value1, Attribute2: value2, ..." # there may be arbitray leading and intermitting whitespace. # 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_keyring: config['use_keyring'] = False 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, path = parse_apisrv_url(config.get('scheme', 'https'), url) apiurl = urljoin(scheme, host, path) creds_mgr = _get_credentials_manager(url, cp) # if the deprecated gnomekeyring is used we should use the apiurl instead of url # (that's what the old code did), but this makes things more complex # (also, it is very unlikely that url and apiurl differ) user = _extract_user_compat(cp, url, creds_mgr) if user is None: raise oscerr.ConfigMissingCredentialsError( 'No user found in section %s' % url, conffile, url) password = creds_mgr.get_password(url, user) if password is None: raise oscerr.ConfigMissingCredentialsError( 'No password found in section %s' % url, conffile, url) if cp.has_option(url, 'http_headers'): http_headers = cp.get(url, 'http_headers') http_headers = http_header_regexp.findall(http_headers) else: http_headers = [] if cp.has_option(url, 'aliases'): for i in cp.get(url, 'aliases').split(','): key = i.strip() if key == '': continue if key in aliases: msg = 'duplicate alias entry: \'%s\' is already used for another apiurl' % key raise oscerr.ConfigError(msg, conffile) aliases[key] = url entry = {'user': user, 'pass': password, 'http_headers': http_headers} api_host_options[apiurl] = APIHostOptionsEntry(entry) optional = ('realname', 'email', 'sslcertck', 'cafile', 'capath') for key in optional: if cp.has_option(url, key): if key == 'sslcertck': api_host_options[apiurl][key] = cp.getboolean(url, key) else: api_host_options[apiurl][key] = cp.get(url, key) if cp.has_option(url, 'build-root', proper=True): api_host_options[apiurl]['build-root'] = cp.get(url, 'build-root', raw=True) if not 'sslcertck' in api_host_options[apiurl]: api_host_options[apiurl]['sslcertck'] = True if scheme == 'http': api_host_options[apiurl]['sslcertck'] = False if cp.has_option(url, 'trusted_prj'): api_host_options[apiurl]['trusted_prj'] = cp.get( url, 'trusted_prj').split(' ') else: api_host_options[apiurl]['trusted_prj'] = [] # add the auth data we collected to the config dict config['api_host_options'] = api_host_options config['apiurl_aliases'] = aliases apiurl = aliases.get(config['apiurl'], config['apiurl']) config['apiurl'] = urljoin(*parse_apisrv_url(None, apiurl)) # backward compatibility if 'apisrv' in config: apisrv = config['apisrv'].lstrip('http://') apisrv = apisrv.lstrip('https://') scheme = config.get('scheme', 'https') config['apiurl'] = urljoin(scheme, apisrv) if 'apisrc' in config or 'scheme' in config: print('Warning: Use of the \'scheme\' or \'apisrv\' in oscrc is deprecated!\n' \ 'Warning: See README for migration details.', file=sys.stderr) if 'build_platform' in config: print( 'Warning: Use of \'build_platform\' config option is deprecated! (use \'build_repository\' instead)', file=sys.stderr) config['build_repository'] = config['build_platform'] if config['plaintext_passwd']: print( 'The \'plaintext_passwd\' option is deprecated and will be ignored', file=sys.stderr) config['verbose'] = int(config['verbose']) # override values which we were called with if override_verbose: config['verbose'] = override_verbose + 1 if override_debug: config['debug'] = override_debug if override_http_debug: config['http_debug'] = override_http_debug if override_http_full_debug: config['http_debug'] = override_http_full_debug or config['http_debug'] config['http_full_debug'] = override_http_full_debug if override_traceback: config['traceback'] = override_traceback if override_post_mortem: config['post_mortem'] = override_post_mortem if override_apiurl: apiurl = aliases.get(override_apiurl, override_apiurl) # check if apiurl is a valid url config['apiurl'] = urljoin(*parse_apisrv_url(None, apiurl)) # XXX unless config['user'] goes away (and is replaced with a handy function, or # config becomes an object, even better), set the global 'user' here as well, # provided that there _are_ credentials for the chosen apiurl: try: config['user'] = get_apiurl_usr(config['apiurl']) except oscerr.ConfigMissingApiurl as e: e.msg = config_missing_apiurl_text % config['apiurl'] e.file = conffile raise e # finally, initialize urllib2 for to use the credentials for Basic Authentication init_basicauth(config, os.stat(conffile).st_mtime)