@@ -1824,29 +1824,33 @@ def get_config(override_conffile=None,
18241824 else :
18251825 conffile = identify_conf ()
18261826
1827- conffile = os .path .expanduser (conffile )
1828- if not os .path .exists (conffile ):
1829- raise oscerr .NoConfigfile (conffile , account_not_configured_text % conffile )
1827+ if conffile in ["" , "/dev/null" ]:
1828+ cp = OscConfigParser .OscConfigParser ()
1829+ cp .add_section ("general" )
1830+ else :
1831+ conffile = os .path .expanduser (conffile )
1832+ if not os .path .exists (conffile ):
1833+ raise oscerr .NoConfigfile (conffile , account_not_configured_text % conffile )
18301834
1831- # make sure oscrc is not world readable, it may contain a password
1832- conffile_stat = os .stat (conffile )
1833- if conffile_stat .st_mode != 0o600 :
1834- try :
1835- os .chmod (conffile , 0o600 )
1836- except OSError as e :
1837- if e .errno in (errno .EROFS , errno .EPERM ):
1838- print (f"Warning: Configuration file '{ conffile } ' may have insecure file permissions." )
1839- else :
1840- raise e
1835+ # make sure oscrc is not world readable, it may contain a password
1836+ conffile_stat = os .stat (conffile )
1837+ if conffile_stat .st_mode != 0o600 :
1838+ try :
1839+ os .chmod (conffile , 0o600 )
1840+ except OSError as e :
1841+ if e .errno in (errno .EROFS , errno .EPERM ):
1842+ print (f"Warning: Configuration file '{ conffile } ' may have insecure file permissions." )
1843+ else :
1844+ raise e
18411845
1842- cp = get_configParser (conffile )
1846+ cp = get_configParser (conffile )
18431847
1844- if not cp .has_section (' general' ):
1845- # FIXME: it might be sufficient to just assume defaults?
1846- msg = config_incomplete_text % conffile
1847- defaults = Options ().dict ()
1848- msg += new_conf_template % defaults
1849- raise oscerr .ConfigError (msg , conffile )
1848+ if not cp .has_section (" general" ):
1849+ # FIXME: it might be sufficient to just assume defaults?
1850+ msg = config_incomplete_text % conffile
1851+ defaults = Options ().dict ()
1852+ msg += new_conf_template % defaults
1853+ raise oscerr .ConfigError (msg , conffile )
18501854
18511855 global config
18521856
@@ -1868,29 +1872,44 @@ def get_config(override_conffile=None,
18681872 urls = [i for i in cp .sections () if i != "general" ]
18691873 for url in urls :
18701874 apiurl = sanitize_apiurl (url )
1871- username = cp [url ].get ("user" , None )
1872- if username is None :
1873- raise oscerr .ConfigMissingCredentialsError (f"No user found in section { url } " , conffile , url )
1874-
1875+ # the username will be overwritten later while reading actual config values
1876+ username = cp [url ].get ("user" , "" )
18751877 host_options = HostOptions (apiurl = apiurl , username = username , _parent = config )
1878+
18761879 known_ini_keys = set ()
18771880 for name , field in host_options .__fields__ .items ():
1881+ # the following code relies on interating through fields in a given order: aliases, username, credentials_mgr_class, password
1882+
18781883 ini_key = field .extra .get ("ini_key" , name )
18791884 known_ini_keys .add (ini_key )
18801885
1881- if name == "password" :
1882- # we need to handle the password first because it may be stored in a keyring instead of a config file
1883- creds_mgr = _get_credentials_manager (url , cp )
1884- value = creds_mgr .get_password (url , host_options .username , defer = True , apiurl = host_options .apiurl )
1885- if value is None :
1886- raise oscerr .ConfigMissingCredentialsError ("No password found in section {url}" , conffile , url )
1887- value = Password (value )
1886+ # iterate through aliases and store the value of the the first env that matches OSC_HOST_{ALIAS}_{NAME}
1887+ env_value = None
1888+ for alias in host_options .aliases :
1889+ alias = alias .replace ("-" , "_" )
1890+ env_key = f"OSC_HOST_{ alias .upper ()} _{ name .upper ()} "
1891+ env_value = os .environ .get (env_key , None )
1892+ if env_value is not None :
1893+ break
1894+
1895+ if env_value is not None :
1896+ value = env_value
18881897 elif ini_key in cp [url ]:
18891898 value = cp [url ][ini_key ]
18901899 else :
1891- continue
1900+ value = None
18921901
1893- host_options .set_value_from_string (name , value )
1902+ if name == "credentials_mgr_class" :
1903+ # HACK: inject credentials_mgr_class back in case we have specified it from env to have it available for reading password
1904+ if value :
1905+ cp [url ][credentials .AbstractCredentialsManager .config_entry ] = value
1906+ elif name == "password" :
1907+ creds_mgr = _get_credentials_manager (url , cp )
1908+ if env_value is None :
1909+ value = creds_mgr .get_password (url , host_options .username , defer = True , apiurl = host_options .apiurl )
1910+
1911+ if value is not None :
1912+ host_options .set_value_from_string (name , value )
18941913
18951914 for key , value in cp [url ].items ():
18961915 if key .startswith ("_" ):
@@ -1941,6 +1960,45 @@ def get_config(override_conffile=None,
19411960
19421961 config .set_value_from_string (name , value )
19431962
1963+ # BEGIN: override credentials for the default apiurl
1964+
1965+ # OSC_APIURL is handled already because it's a regular field
1966+ env_username = os .environ .get ("OSC_USERNAME" , "" )
1967+ env_credentials_mgr_class = os .environ .get ("OSC_CREDENTIALS_MGR_CLASS" , None )
1968+ env_password = os .environ .get ("OSC_PASSWORD" , None )
1969+
1970+ if config .apiurl not in config .api_host_options :
1971+ host_options = HostOptions (apiurl = config .apiurl , username = env_username , _parent = config )
1972+ config .api_host_options [config .apiurl ] = host_options
1973+ # HACK: inject section so we can add credentials_mgr_class later
1974+ cp .add_section (config .apiurl )
1975+
1976+ host_options = config .api_host_options [config .apiurl ]
1977+ if env_username :
1978+ host_options .set_value_from_string ("username" , env_username )
1979+
1980+ if env_credentials_mgr_class :
1981+ host_options .set_value_from_string ("credentials_mgr_class" , env_credentials_mgr_class )
1982+ # HACK: inject credentials_mgr_class in case we have specified it from env to have it available for reading password
1983+ cp [config .apiurl ]["credentials_mgr_class" ] = env_credentials_mgr_class
1984+
1985+ if env_password :
1986+ password = Password (env_password )
1987+ host_options .password = password
1988+ elif env_credentials_mgr_class :
1989+ creds_mgr = _get_credentials_manager (config .apiurl , cp )
1990+ password = creds_mgr .get_password (config .apiurl , host_options .username , defer = True , apiurl = host_options .apiurl )
1991+ host_options .password = password
1992+
1993+ # END: override credentials for the default apiurl
1994+
1995+ for apiurl , host_options in config .api_host_options .items ():
1996+ if not host_options .username :
1997+ raise oscerr .ConfigMissingCredentialsError (f"No user configured for apiurl { apiurl } " , conffile , apiurl )
1998+
1999+ if not host_options .password :
2000+ raise oscerr .ConfigMissingCredentialsError (f"No password configured for apiurl { apiurl } " , conffile , apiurl )
2001+
19442002 for key , value in cp ["general" ].items ():
19452003 if key .startswith ("_" ):
19462004 continue
0 commit comments