Ejemplo n.º 1
0
Archivo: conf.py Proyecto: jfding/osc
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)