Don't expose user credentials
When --test-accounts is used, don't print any user credentials to a tempest.conf file. Depends-On: https://review.openstack.org/#/c/570822/ Change-Id: Ic7977ed9e0e03d04aca446407b22a9a73c2dca98
This commit is contained in:
parent
bc17fffac7
commit
ed5163e729
@ -27,6 +27,25 @@ DEFAULT_IMAGE = ("http://download.cirros-cloud.net/0.3.5/"
|
||||
"cirros-0.3.5-x86_64-disk.img")
|
||||
DEFAULT_IMAGE_FORMAT = 'qcow2'
|
||||
|
||||
# The dict holds the credentials, which are not supposed to be printed
|
||||
# to a tempest.conf when --test-accounts CLI parameter is used.
|
||||
ALL_CREDENTIALS_KEYS = {
|
||||
"auth.admin_username": [],
|
||||
"auth.admin_password": [],
|
||||
"auth.admin_project_name": [],
|
||||
"auth.admin_domain_name": [],
|
||||
"identity.username": [],
|
||||
"identity.password": [],
|
||||
"identity.tenant_name": [],
|
||||
"identity.alt_username": [],
|
||||
"identity.alt_password": [],
|
||||
"identity.alt_tenant_name": [],
|
||||
"identity.admin_username": [],
|
||||
"identity.admin_password": [],
|
||||
"identity.admin_tenant_name": [],
|
||||
"identity.admin_domain_name": [],
|
||||
}
|
||||
|
||||
# services and their codenames
|
||||
SERVICE_NAMES = {
|
||||
'baremetal': 'ironic',
|
||||
|
@ -359,7 +359,8 @@ def config_tempest(**kwargs):
|
||||
remove = parse_values_to_remove(kwargs.get('remove', []))
|
||||
set_logging(kwargs.get('debug', False), kwargs.get('verbose', False))
|
||||
|
||||
conf = tempest_conf.TempestConf()
|
||||
write_credentials = kwargs.get('test_accounts') is None
|
||||
conf = tempest_conf.TempestConf(write_credentials=write_credentials)
|
||||
set_options(conf, kwargs.get('deployer_input'),
|
||||
kwargs.get('non_admin', False),
|
||||
kwargs.get('overrides', []), kwargs.get('test_accounts'),
|
||||
@ -403,9 +404,7 @@ def config_tempest(**kwargs):
|
||||
LOG.info("Removing configuration: %s", str(remove))
|
||||
conf.remove_values(remove)
|
||||
out_path = kwargs.get('out', 'etc/tempest.conf')
|
||||
LOG.info("Creating configuration file %s", os.path.abspath(out_path))
|
||||
with open(out_path, 'w') as f:
|
||||
conf.write(f)
|
||||
conf.write(out_path)
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -14,9 +14,10 @@
|
||||
# under the License.
|
||||
|
||||
import ConfigParser
|
||||
import os
|
||||
import sys
|
||||
|
||||
from constants import LOG
|
||||
import constants as C
|
||||
from oslo_config import cfg
|
||||
import tempest.config
|
||||
|
||||
@ -31,6 +32,10 @@ class TempestConf(ConfigParser.SafeConfigParser):
|
||||
|
||||
CONF = tempest.config.TempestConfigPrivate(parse_conf=False)
|
||||
|
||||
def __init__(self, write_credentials=True, **kwargs):
|
||||
self.write_credentials = write_credentials
|
||||
ConfigParser.SafeConfigParser.__init__(self, **kwargs)
|
||||
|
||||
def get_bool_value(self, value):
|
||||
"""Returns boolean value of the string value given.
|
||||
|
||||
@ -63,7 +68,8 @@ class TempestConf(ConfigParser.SafeConfigParser):
|
||||
else:
|
||||
return self.CONF.get(section).get(key)
|
||||
except cfg.NoSuchOptError:
|
||||
LOG.warning("Option %s is not defined in %s section", key, section)
|
||||
C.LOG.warning("Option %s is not defined in %s section",
|
||||
key, section)
|
||||
|
||||
def set(self, section, key, value, priority=False):
|
||||
"""Set value in configuration, similar to `SafeConfigParser.set`
|
||||
@ -88,16 +94,25 @@ class TempestConf(ConfigParser.SafeConfigParser):
|
||||
if not self.has_section(section) and section.lower() != "default":
|
||||
self.add_section(section)
|
||||
if not priority and (section, key) in self.priority_sectionkeys:
|
||||
LOG.debug("Option '[%s] %s = %s' was defined by user, NOT"
|
||||
C.LOG.debug("Option '[%s] %s = %s' was defined by user, NOT"
|
||||
" overwriting into value '%s'", section, key,
|
||||
self.get(section, key), value)
|
||||
return False
|
||||
if priority:
|
||||
self.priority_sectionkeys.add((section, key))
|
||||
LOG.debug("Setting [%s] %s = %s", section, key, value)
|
||||
C.LOG.debug("Setting [%s] %s = %s", section, key, value)
|
||||
ConfigParser.SafeConfigParser.set(self, section, key, value)
|
||||
return True
|
||||
|
||||
def write(self, out_path):
|
||||
C.LOG.info("Creating configuration file %s", os.path.abspath(out_path))
|
||||
if not self.write_credentials:
|
||||
C.LOG.info("Credentials will not be printed to a tempest.conf, "
|
||||
"writing credentials is disabled.")
|
||||
self.remove_values(C.ALL_CREDENTIALS_KEYS)
|
||||
with open(out_path, 'w') as f:
|
||||
ConfigParser.SafeConfigParser.write(self, f)
|
||||
|
||||
def remove_values(self, to_remove):
|
||||
"""Remove values from configuration file specified in arguments.
|
||||
|
||||
@ -125,7 +140,7 @@ class TempestConf(ConfigParser.SafeConfigParser):
|
||||
self.set(section, key, ",".join(conf_values))
|
||||
except ConfigParser.NoOptionError:
|
||||
# only inform a user, option specified by him doesn't exist
|
||||
LOG.error(sys.exc_info()[1])
|
||||
C.LOG.error(sys.exc_info()[1])
|
||||
except ConfigParser.NoSectionError:
|
||||
# only inform a user, section specified by him doesn't exist
|
||||
LOG.error(sys.exc_info()[1])
|
||||
C.LOG.error(sys.exc_info()[1])
|
||||
|
@ -102,7 +102,7 @@ class TestTempestConf(BaseConfigTempestTest):
|
||||
else:
|
||||
self.assertTrue(ext in conf_exts)
|
||||
|
||||
@mock.patch('config_tempest.tempest_conf.LOG')
|
||||
@mock.patch('config_tempest.tempest_conf.C.LOG')
|
||||
def test_remove_not_defined_values(self, mock_logging):
|
||||
self.conf.remove_values({"notExistSection.key": []})
|
||||
# check if LOG.error was called
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
When --test-accounts parameter (specifying a path to a accounts.yaml file)
|
||||
is used, don't write any user credentials to tempest.conf.
|
||||
This will make it easier for users who run tempest tests with accounts.yaml
|
||||
file and want to share their tempest.conf without exposing their credentials.
|
Loading…
Reference in New Issue
Block a user