summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cammarata <jimi@sngx.net>2015-09-17 11:03:54 -0400
committerJames Cammarata <jimi@sngx.net>2015-09-17 11:03:54 -0400
commitd875699ac2f1a7f8b71a535c5be8642dd4cb5a0e (patch)
tree1fae58a36b26717f6769aea602dbe46b94c964f1
parent8532ddd5ed7dc713cef1cf7440e6f61aabde8f77 (diff)
parentba82e574453db45f1c647733acaace415cb2f17e (diff)
downloadansible-d875699ac2f1a7f8b71a535c5be8642dd4cb5a0e.tar.gz
Merge branch 'apollo13-sudo_on_if_needed' into devel
-rw-r--r--docsite/rst/intro_configuration.rst12
-rw-r--r--lib/ansible/constants.py1
-rw-r--r--lib/ansible/plugins/action/__init__.py4
-rw-r--r--test/units/plugins/action/test_action.py57
4 files changed, 73 insertions, 1 deletions
diff --git a/docsite/rst/intro_configuration.rst b/docsite/rst/intro_configuration.rst
index aa64807613..0e0e6deb64 100644
--- a/docsite/rst/intro_configuration.rst
+++ b/docsite/rst/intro_configuration.rst
@@ -699,6 +699,18 @@ Ask for privilege escalation password, the default is False::
become_ask_pass=True
+.. _become_allow_same_user:
+
+become_allow_same_user
+======================
+
+Most of the time, using *sudo* to run a command as the same user who is running
+*sudo* itself is unnecessary overhead, so Ansible does not allow it. However,
+depending on the *sudo* configuration, it may be necessary to run a command as
+the same user through *sudo*, such as to switch SELinux contexts. For this
+reason, you can set ``become_allow_same_user`` to ``True`` and disable this
+optimization.
+
.. _paramiko_settings:
Paramiko Specific Settings
diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py
index e7fec130e2..73401288ef 100644
--- a/lib/ansible/constants.py
+++ b/lib/ansible/constants.py
@@ -173,6 +173,7 @@ DEFAULT_ASK_SUDO_PASS = get_config(p, DEFAULTS, 'ask_sudo_pass', 'ANSIBLE
# Become
BECOME_ERROR_STRINGS = {'sudo': 'Sorry, try again.', 'su': 'Authentication failure', 'pbrun': '', 'pfexec': '', 'runas': '', 'doas': 'Permission denied'} #FIXME: deal with i18n
BECOME_METHODS = ['sudo','su','pbrun','pfexec','runas','doas']
+BECOME_ALLOW_SAME_USER = get_config(p, 'privilege_escalation', 'become_allow_same_user', 'ANSIBLE_BECOME_ALLOW_SAME_USER', False, boolean=True)
DEFAULT_BECOME_METHOD = get_config(p, 'privilege_escalation', 'become_method', 'ANSIBLE_BECOME_METHOD','sudo' if DEFAULT_SUDO else 'su' if DEFAULT_SU else 'sudo' ).lower()
DEFAULT_BECOME = get_config(p, 'privilege_escalation', 'become', 'ANSIBLE_BECOME',False, boolean=True)
DEFAULT_BECOME_USER = get_config(p, 'privilege_escalation', 'become_user', 'ANSIBLE_BECOME_USER', 'root')
diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py
index 72f7a3fc9a..aa3c630ebb 100644
--- a/lib/ansible/plugins/action/__init__.py
+++ b/lib/ansible/plugins/action/__init__.py
@@ -453,7 +453,9 @@ class ActionBase:
self._display.debug("no command, exiting _low_level_execute_command()")
return dict(stdout='', stderr='')
- if sudoable and self._play_context.become:
+ allow_same_user = C.BECOME_ALLOW_SAME_USER
+ same_user = self._play_context.become_user == self._play_context.remote_user
+ if sudoable and self._play_context.become and (allow_same_user or not same_user):
self._display.debug("using become for this command")
cmd = self._play_context.make_become_cmd(cmd, executable=executable)
diff --git a/test/units/plugins/action/test_action.py b/test/units/plugins/action/test_action.py
new file mode 100644
index 0000000000..24fd325993
--- /dev/null
+++ b/test/units/plugins/action/test_action.py
@@ -0,0 +1,57 @@
+# (c) 2015, Florian Apolloner <florian@apolloner.eu>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+from ansible import constants as C
+from ansible.compat.tests import unittest
+from ansible.compat.tests.mock import Mock
+from ansible.playbook.play_context import PlayContext
+from ansible.plugins.action import ActionBase
+
+
+class TestActionBase(unittest.TestCase):
+
+ def test_sudo_only_if_user_differs(self):
+ play_context = PlayContext()
+ action_base = ActionBase(None, None, play_context, None, None, None)
+ action_base._connection = Mock(exec_command=Mock(return_value=(0, '', '', '')))
+
+ play_context.become = True
+ play_context.become_user = play_context.remote_user = 'root'
+ play_context.make_become_cmd = Mock(return_value='CMD')
+
+ action_base._low_level_execute_command('ECHO', '/tmp', sudoable=True)
+ play_context.make_become_cmd.assert_not_called()
+
+ play_context.remote_user = 'apo'
+ action_base._low_level_execute_command('ECHO', '/tmp', sudoable=True)
+ play_context.make_become_cmd.assert_called_once_with('ECHO', executable=None)
+
+ play_context.make_become_cmd.reset_mock()
+
+ become_allow_same_user = C.BECOME_ALLOW_SAME_USER
+ C.BECOME_ALLOW_SAME_USER = True
+ try:
+ play_context.remote_user = 'root'
+ action_base._low_level_execute_command('ECHO SAME', '/tmp', sudoable=True)
+ play_context.make_become_cmd.assert_called_once_with('ECHO SAME', executable=None)
+ finally:
+ C.BECOME_ALLOW_SAME_USER = become_allow_same_user