Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rhsm modules: cleanly fail when not run as root #6211

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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