Skip to content

Commit

Permalink
rhsm modules: cleanly fail when not run as root (#6211)
Browse files Browse the repository at this point in the history
subscription-manager on RHEL installs a symlink in /usr/bin to
console-helper (part of usermode), which triggers an interactive prompt
for root credentials when run as user. It seems that console-helper
does not handle well non-interactive contexts (e.g. without a TTY for
input), and thus it will hang waiting for input when run as user in an
Ansible task.

Since subscription-manager requires root already anyway (and it will
fail when explicitly run as user), then apply the same logic locally on
all the modules that interact with it: redhat_subscription,
rhsm_release, and rhsm_repository.

(cherry picked from commit 9f67cbb)
  • Loading branch information
ptoscano authored and patchback[bot] committed Mar 22, 2023
1 parent 20bd0d1 commit 38135c0
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 4 deletions.
6 changes: 6 additions & 0 deletions changelogs/fragments/6211-rhsm-require-root.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bugfixes:
- redhat_subscription, rhsm_release, rhsm_repository - cleanly fail when not running as root,
rather than hanging on an interactive ``console-helper`` prompt; they all interact with
``subscription-manager``, which already requires to be run as root
(https://github.com/ansible-collections/community.general/issues/734,
https://github.com/ansible-collections/community.general/pull/6211).
9 changes: 8 additions & 1 deletion plugins/modules/redhat_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
I(server_proxy_hostname), I(server_proxy_port), I(server_proxy_user) and
I(server_proxy_password) are no longer taken from the C(/etc/rhsm/rhsm.conf)
config file and default to None.
- It is possible to interact with C(subscription-manager) only as root,
so root permissions are required to successfully run this module.
requirements:
- subscription-manager
- Optionally the C(dbus) Python library; this is usually included in the OS
Expand Down Expand Up @@ -291,7 +293,7 @@
'''

from os.path import isfile
from os import unlink
from os import getuid, unlink
import re
import shutil
import tempfile
Expand Down Expand Up @@ -1074,6 +1076,11 @@ def main():
required_if=[['state', 'present', ['username', 'activationkey', 'token'], True]],
)

if getuid() != 0:
module.fail_json(
msg="Interacting with subscription-manager requires root permissions ('become: true')"
)

rhsm.module = module
state = module.params['state']
username = module.params['username']
Expand Down
8 changes: 8 additions & 0 deletions plugins/modules/rhsm_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
- This module will fail on an unregistered system.
Use the C(redhat_subscription) module to register a system
prior to setting the RHSM release.
- It is possible to interact with C(subscription-manager) only as root,
so root permissions are required to successfully run this module.
requirements:
- Red Hat Enterprise Linux 6+ with subscription-manager installed
extends_documentation_fragment:
Expand Down Expand Up @@ -63,6 +65,7 @@

from ansible.module_utils.basic import AnsibleModule

import os
import re

# Matches release-like values such as 7.2, 5.10, 6Server, 8
Expand Down Expand Up @@ -109,6 +112,11 @@ def main():
supports_check_mode=True
)

if os.getuid() != 0:
module.fail_json(
msg="Interacting with subscription-manager requires root permissions ('become: true')"
)

target_release = module.params['release']

# sanity check: the target release at least looks like a valid release
Expand Down
12 changes: 9 additions & 3 deletions plugins/modules/rhsm_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
notes:
- In order to manage RHSM repositories the system must be already registered
to RHSM manually or using the Ansible C(redhat_subscription) module.
- It is possible to interact with C(subscription-manager) only as root,
so root permissions are required to successfully run this module.
requirements:
- subscription-manager
Expand Down Expand Up @@ -100,9 +102,7 @@ def run_subscription_manager(module, arguments):
lang_env = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')
rc, out, err = module.run_command("%s %s" % (rhsm_bin, " ".join(arguments)), environ_update=lang_env)

if rc == 1 and (err == 'The password you typed is invalid.\nPlease try again.\n' or os.getuid() != 0):
module.fail_json(msg='The executable file subscription-manager must be run using root privileges')
elif rc == 0 and out == 'This system has no repositories available through subscriptions.\n':
if rc == 0 and out == 'This system has no repositories available through subscriptions.\n':
module.fail_json(msg='This system has no repositories available through subscriptions')
elif rc == 1:
module.fail_json(msg='subscription-manager failed with the following error: %s' % err)
Expand Down Expand Up @@ -243,6 +243,12 @@ def main():
),
supports_check_mode=True,
)

if os.getuid() != 0:
module.fail_json(
msg="Interacting with subscription-manager requires root permissions ('become: true')"
)

name = module.params['name']
state = module.params['state']
purge = module.params['purge']
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/plugins/modules/test_redhat_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def patch_redhat_subscription(mocker):
return_value='/testbin/subscription-manager')
mocker.patch('ansible_collections.community.general.plugins.modules.redhat_subscription.Rhsm._can_connect_to_dbus',
return_value=False)
mocker.patch('ansible_collections.community.general.plugins.modules.redhat_subscription.getuid',
return_value=0)


@pytest.mark.parametrize('patch_ansible_module', [{}], indirect=['patch_ansible_module'])
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/plugins/modules/test_rhsm_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@ def setUp(self):
self.get_bin_path = self.mock_get_bin_path.start()
self.get_bin_path.return_value = '/testbin/subscription-manager'

# subscription-manager needs to be run as root
self.mock_os_getuid = patch('ansible_collections.community.general.plugins.modules.rhsm_release.'
'os.getuid')
self.os_getuid = self.mock_os_getuid.start()
self.os_getuid.return_value = 0

def tearDown(self):
self.mock_run_command.stop()
self.mock_get_bin_path.stop()
self.mock_os_getuid.stop()
super(RhsmRepositoryReleaseModuleTestCase, self).tearDown()

def module_main(self, exit_exc):
Expand Down

0 comments on commit 38135c0

Please sign in to comment.