Make ~/.tripleo/history owned by the correct user

When a tripleo subcommand command is executed with sudo, we identify
the original user and create the history file in that user's home
directory.

When creating the file, we should make that user owns it, otherwise
the user no longer able to run tripleo subcommends without sudo once
the history file is created and owned by root.

Change-Id: Ie6195b629fa65bcf9e5350f73d332e5034e8039b
(cherry picked from commit bd70bcaa2c)
(cherry picked from commit d4b5576c39)
This commit is contained in:
Takashi Kajinami 2022-10-20 13:23:47 +09:00
parent b751bcdc38
commit c945e677df
2 changed files with 69 additions and 23 deletions

View File

@ -15,8 +15,8 @@
import ansible_runner
import argparse
import datetime
import errno
import fixtures
import logging
import mock
@ -1355,34 +1355,65 @@ class TestGetSingleIp(TestCase):
class TestStoreCliParam(TestCase):
def setUp(self):
self.args = argparse.ArgumentParser()
class ArgsFake(object):
def __init__(self):
self.a = 1
self.args = ArgsFake()
@mock.patch('os.path.isdir')
@mock.patch('os.path.exists')
def test_exists_but_not_dir(self, mock_exists, mock_isdir):
mock_exists.return_value = True
@mock.patch('os.chown')
@mock.patch('os.mkdir')
def test_non_directory_exists(self, mock_mkdir, mock_chown, mock_isdir):
mock_isdir.return_value = False
self.assertRaises(exceptions.InvalidConfiguration,
utils.store_cli_param,
"overcloud deploy", self.args)
@mock.patch('tripleoclient.utils.datetime')
@mock.patch('os.path.isdir')
@mock.patch('os.path.exists')
def test_write_cli_param(self, mock_exists, mock_isdir):
@mock.patch('os.chown')
@mock.patch('os.mkdir')
def test_directory_exists(self, mock_mkdir, mock_chown, mock_isdir,
mock_date):
history_path = os.path.join(os.path.expanduser("~"), '.tripleo')
mock_exists.return_value = True
mock_mkdir.side_effect = OSError(errno.EEXIST, 'error')
mock_isdir.return_value = True
mock_file = mock.mock_open()
mock_date.datetime.now.return_value = datetime.datetime(2017, 11, 22)
class ArgsFake(object):
def __init__(self):
self.a = 1
dt = datetime.datetime(2017, 11, 22)
with mock.patch("builtins.open", mock_file):
with mock.patch('tripleoclient.utils.datetime') as mock_date:
mock_date.datetime.now.return_value = dt
utils.store_cli_param("overcloud plan list", ArgsFake())
utils.store_cli_param("overcloud plan list", self.args)
expected_call = [
mock.call("%s/history" % history_path, 'a'),
mock.call().write('2017-11-22 00:00:00 overcloud-plan-list a=1 \n')
]
mock_file.assert_has_calls(expected_call, any_order=True)
@mock.patch('os.path.isdir')
@mock.patch('os.chown')
@mock.patch('os.mkdir')
def test_directory_fail(self, mock_mkdir, mock_chown, mock_isdir):
mock_mkdir.side_effect = OSError()
with self.assertRaises(IOError):
utils.store_cli_param("overcloud plan list", self.args)
mock_chown.assert_not_called()
mock_isdir.assert_not_called()
@mock.patch('tripleoclient.utils.datetime')
@mock.patch('os.path.isdir')
@mock.patch('os.chown')
@mock.patch('os.mkdir')
def test_write_cli_param(self, mock_mkdir, mock_chown, mock_isdir,
mock_date):
history_path = os.path.join(os.path.expanduser("~"), '.tripleo')
mock_isdir.return_value = True
mock_file = mock.mock_open()
mock_date.datetime.now.return_value = datetime.datetime(2017, 11, 22)
with mock.patch("builtins.open", mock_file):
utils.store_cli_param("overcloud plan list", self.args)
expected_call = [
mock.call("%s/history" % history_path, 'a'),
@ -1392,12 +1423,14 @@ class TestStoreCliParam(TestCase):
@mock.patch('builtins.open')
@mock.patch('os.path.isdir')
@mock.patch('os.path.exists')
def test_fail_to_write_data(self, mock_exists, mock_isdir, mock_open):
mock_exists.return_value = True
@mock.patch('os.chown')
@mock.patch('os.mkdir')
def test_fail_to_write_data(self, mock_mkdir, mock_chown, mock_isdir,
mock_open):
mock_isdir.return_value = True
mock_open.side_effect = IOError()
self.assertRaises(IOError, utils.store_cli_param, "command", self.args)
with self.assertRaises(IOError):
utils.store_cli_param("command", self.args)
class ProcessMultipleEnvironments(TestCase):

View File

@ -863,16 +863,29 @@ def store_cli_param(command_name, parsed_args):
command_name = command_name.replace(" ", "-")
history_path = os.path.join(constants.CLOUD_HOME_DIR, '.tripleo')
makedirs(history_path)
try:
os.mkdir(history_path, 0o700)
os.chown(history_path,
int(os.environ.get('SUDO_UID', -1)),
int(os.environ.get('SUDO_GID', -1)))
except OSError as e:
if e.errno != errno.EEXIST:
messages = _("Unable to create the .tripleo directory: "
"{0}, {1}").format(history_path, e)
raise IOError(messages)
if os.path.isdir(history_path):
try:
with open(os.path.join(history_path,
'history'), 'a') as history:
history_file_path = os.path.join(history_path, 'history')
with open(history_file_path, 'a') as history:
args = parsed_args.__dict__.copy()
used_args = ', '.join('%s=%s' % (key, value)
for key, value in args.items())
history.write(' '.join([str(datetime.datetime.now()),
str(command_name), used_args, "\n"]))
os.chown(history_file_path,
int(os.environ.get('SUDO_UID', -1)),
int(os.environ.get('SUDO_GID', -1)))
except IOError as e:
messages = _("Unable to write into TripleO history file: "
"{0}, {1}").format(history_path, e)