Fix running unknown commands in daemon mode
Running a unknown command (which is mentioned in the filter but not available on the filesystem) leads currently to an exception. Make sure that the return codes for both, daemon and non-daemon mode are equal when running the same command. Also add functional tests for this case. Change-Id: I20004c3c370d004b5b76f4c8f8ab167d0949fabf Closes-Bug: #1632768
This commit is contained in:
parent
e93f837005
commit
16c22e9b1a
|
@ -27,6 +27,7 @@ import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
from oslo_rootwrap import cmd
|
||||||
from oslo_rootwrap import jsonrpc
|
from oslo_rootwrap import jsonrpc
|
||||||
from oslo_rootwrap import subprocess
|
from oslo_rootwrap import subprocess
|
||||||
from oslo_rootwrap import wrapper
|
from oslo_rootwrap import wrapper
|
||||||
|
@ -45,6 +46,7 @@ class RootwrapClass(object):
|
||||||
self.filters = filters
|
self.filters = filters
|
||||||
|
|
||||||
def run_one_command(self, userargs, stdin=None):
|
def run_one_command(self, userargs, stdin=None):
|
||||||
|
try:
|
||||||
obj = wrapper.start_subprocess(
|
obj = wrapper.start_subprocess(
|
||||||
self.filters, userargs,
|
self.filters, userargs,
|
||||||
exec_dirs=self.config.exec_dirs,
|
exec_dirs=self.config.exec_dirs,
|
||||||
|
@ -53,6 +55,16 @@ class RootwrapClass(object):
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE)
|
||||||
|
except wrapper.FilterMatchNotExecutable:
|
||||||
|
LOG.warning("Executable not found for: %s",
|
||||||
|
' '.join(userargs))
|
||||||
|
return cmd.RC_NOEXECFOUND, "", ""
|
||||||
|
|
||||||
|
except wrapper.NoFilterMatched:
|
||||||
|
LOG.warning("Unauthorized command: %s (no filter matched)",
|
||||||
|
' '.join(userargs))
|
||||||
|
return cmd.RC_UNAUTHORIZED, "", ""
|
||||||
|
|
||||||
if six.PY3 and stdin is not None:
|
if six.PY3 and stdin is not None:
|
||||||
stdin = os.fsencode(stdin)
|
stdin = os.fsencode(stdin)
|
||||||
out, err = obj.communicate(stdin)
|
out, err = obj.communicate(stdin)
|
||||||
|
|
|
@ -34,9 +34,9 @@ import testtools
|
||||||
from testtools import content
|
from testtools import content
|
||||||
|
|
||||||
from oslo_rootwrap import client
|
from oslo_rootwrap import client
|
||||||
|
from oslo_rootwrap import cmd
|
||||||
from oslo_rootwrap import subprocess
|
from oslo_rootwrap import subprocess
|
||||||
from oslo_rootwrap.tests import run_daemon
|
from oslo_rootwrap.tests import run_daemon
|
||||||
from oslo_rootwrap import wrapper
|
|
||||||
|
|
||||||
|
|
||||||
class _FunctionalBase(object):
|
class _FunctionalBase(object):
|
||||||
|
@ -57,6 +57,7 @@ echo: CommandFilter, /bin/echo, root
|
||||||
cat: CommandFilter, /bin/cat, root
|
cat: CommandFilter, /bin/cat, root
|
||||||
sh: CommandFilter, /bin/sh, root
|
sh: CommandFilter, /bin/sh, root
|
||||||
id: CommandFilter, /usr/bin/id, nobody
|
id: CommandFilter, /usr/bin/id, nobody
|
||||||
|
unknown_cmd: CommandFilter, /unknown/unknown_cmd, root
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def _test_run_once(self, expect_byte=True):
|
def _test_run_once(self, expect_byte=True):
|
||||||
|
@ -83,6 +84,14 @@ id: CommandFilter, /usr/bin/id, nobody
|
||||||
self.assertEqual(expect_out, out)
|
self.assertEqual(expect_out, out)
|
||||||
self.assertEqual(expect_err, err)
|
self.assertEqual(expect_err, err)
|
||||||
|
|
||||||
|
def test_run_command_not_found(self):
|
||||||
|
code, out, err = self.execute(['unknown_cmd'])
|
||||||
|
self.assertEqual(cmd.RC_NOEXECFOUND, code)
|
||||||
|
|
||||||
|
def test_run_unauthorized_command(self):
|
||||||
|
code, out, err = self.execute(['unauthorized_cmd'])
|
||||||
|
self.assertEqual(cmd.RC_UNAUTHORIZED, code)
|
||||||
|
|
||||||
def test_run_as(self):
|
def test_run_as(self):
|
||||||
if os.getuid() != 0:
|
if os.getuid() != 0:
|
||||||
self.skip('Test requires root (for setuid)')
|
self.skip('Test requires root (for setuid)')
|
||||||
|
@ -183,9 +192,6 @@ class RootwrapDaemonTest(_FunctionalBase, testtools.TestCase):
|
||||||
def test_run_with_stdin(self):
|
def test_run_with_stdin(self):
|
||||||
self._test_run_with_stdin(expect_byte=False)
|
self._test_run_with_stdin(expect_byte=False)
|
||||||
|
|
||||||
def test_error_propagation(self):
|
|
||||||
self.assertRaises(wrapper.NoFilterMatched, self.execute, ['other'])
|
|
||||||
|
|
||||||
def test_daemon_ressurection(self):
|
def test_daemon_ressurection(self):
|
||||||
# Let the client start a daemon
|
# Let the client start a daemon
|
||||||
self.execute(['cat'])
|
self.execute(['cat'])
|
||||||
|
|
Loading…
Reference in New Issue