relinker: Add option to drop privileges
Some deployments may need to run the relinker as root -- for example, because /etc/swift/swift.conf is only readable by root. In that case, we need to drop back to the swift user before relinking, or the newly-created partitions will not be readable by the object-server. Co-Authored-By: Alistair Coles <alistairncoles@gmail.com> Change-Id: Ifb9a6acdbc81b68788aa167b4e0eb915620b92f4
This commit is contained in:
parent
1b7dd34d38
commit
7e6f9e7bf0
|
@ -25,7 +25,7 @@ from swift.common.storage_policy import POLICIES
|
|||
from swift.common.exceptions import DiskFileDeleted, DiskFileNotExist, \
|
||||
DiskFileQuarantined
|
||||
from swift.common.utils import replace_partition_in_path, config_true_value, \
|
||||
audit_location_generator, get_logger, readconf
|
||||
audit_location_generator, get_logger, readconf, drop_privileges
|
||||
from swift.obj import diskfile
|
||||
|
||||
|
||||
|
@ -333,6 +333,8 @@ def main(args):
|
|||
dest='swift_dir', help='Path to swift directory')
|
||||
parser.add_argument('--devices', default=None,
|
||||
dest='devices', help='Path to swift device directory')
|
||||
parser.add_argument('--user', default=None, dest='user',
|
||||
help='Drop privileges to this user before relinking')
|
||||
parser.add_argument('--device', default=None, dest='device',
|
||||
help='Device name to relink (default: all)')
|
||||
parser.add_argument('--skip-mount-check', default=False,
|
||||
|
@ -348,9 +350,15 @@ def main(args):
|
|||
conf = readconf(args.conf_file, 'object-relinker')
|
||||
if args.debug:
|
||||
conf['log_level'] = 'DEBUG'
|
||||
user = args.user or conf.get('user')
|
||||
if user:
|
||||
drop_privileges(user)
|
||||
logger = get_logger(conf)
|
||||
else:
|
||||
conf = {}
|
||||
if args.user:
|
||||
# Drop privs before creating log file
|
||||
drop_privileges(args.user)
|
||||
logging.basicConfig(
|
||||
format='%(message)s',
|
||||
level=logging.DEBUG if args.debug else logging.INFO,
|
||||
|
|
|
@ -15,6 +15,7 @@ import binascii
|
|||
import errno
|
||||
import fcntl
|
||||
import json
|
||||
from contextlib import contextmanager
|
||||
import logging
|
||||
from textwrap import dedent
|
||||
|
||||
|
@ -95,6 +96,54 @@ class TestRelinker(unittest.TestCase):
|
|||
shutil.rmtree(self.testdir, ignore_errors=1)
|
||||
storage_policy.reload_storage_policies()
|
||||
|
||||
def _do_test_relinker_drop_privileges(self, command):
|
||||
@contextmanager
|
||||
def do_mocks():
|
||||
# attach mocks to call_capture so that call order can be asserted
|
||||
call_capture = mock.Mock()
|
||||
with mock.patch('swift.cli.relinker.drop_privileges') as mock_dp:
|
||||
with mock.patch('swift.cli.relinker.' + command,
|
||||
return_value=0) as mock_command:
|
||||
call_capture.attach_mock(mock_dp, 'drop_privileges')
|
||||
call_capture.attach_mock(mock_command, command)
|
||||
yield call_capture
|
||||
|
||||
# no user option
|
||||
with do_mocks() as capture:
|
||||
self.assertEqual(0, relinker.main([command]))
|
||||
self.assertEqual([(command, mock.ANY, mock.ANY)],
|
||||
capture.method_calls)
|
||||
|
||||
# cli option --user
|
||||
with do_mocks() as capture:
|
||||
self.assertEqual(0, relinker.main([command, '--user', 'cli_user']))
|
||||
self.assertEqual([('drop_privileges', ('cli_user',), {}),
|
||||
(command, mock.ANY, mock.ANY)],
|
||||
capture.method_calls)
|
||||
|
||||
# cli option --user takes precedence over conf file user
|
||||
with do_mocks() as capture:
|
||||
with mock.patch('swift.cli.relinker.readconf',
|
||||
return_value={'user': 'conf_user'}):
|
||||
self.assertEqual(0, relinker.main([command, 'conf_file',
|
||||
'--user', 'cli_user']))
|
||||
self.assertEqual([('drop_privileges', ('cli_user',), {}),
|
||||
(command, mock.ANY, mock.ANY)],
|
||||
capture.method_calls)
|
||||
|
||||
# conf file user
|
||||
with do_mocks() as capture:
|
||||
with mock.patch('swift.cli.relinker.readconf',
|
||||
return_value={'user': 'conf_user'}):
|
||||
self.assertEqual(0, relinker.main([command, 'conf_file']))
|
||||
self.assertEqual([('drop_privileges', ('conf_user',), {}),
|
||||
(command, mock.ANY, mock.ANY)],
|
||||
capture.method_calls)
|
||||
|
||||
def test_relinker_drop_privileges(self):
|
||||
self._do_test_relinker_drop_privileges('relink')
|
||||
self._do_test_relinker_drop_privileges('cleanup')
|
||||
|
||||
def test_conf_file(self):
|
||||
config = """
|
||||
[DEFAULT]
|
||||
|
|
Loading…
Reference in New Issue