Repository: ansible-collections/community.general

Issue:
redhat_subscription doesn't exit with error, if privilege escalation is not enabled.
##### SUMMARY
When I use the redhat_subscription module to subscribe a RHEL8 machine without enabling privilege escalation with ```become=true``` 
, the task doesn't exit with an error. It just keeps waiting for an input it's never going to get. 

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
redhat_subscription

##### ANSIBLE VERSION

```ansible 2.9.10
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/rodli/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.5 (default, Jul 20 2020, 00:00:00) [GCC 10.1.1 20200507 (Red Hat 10.1.1-1)]```

##### CONFIGURATION

```DEFAULT_HOST_LIST(/home/rodli/ansible/ansible.cfg) = ['/home/rodli/ansible/inventory']```

##### OS / ENVIRONMENT

```
NAME=Fedora
VERSION="32 (Workstation Edition)"
ID=fedora
VERSION_ID=32
VERSION_CODENAME=""
PLATFORM_ID="platform:f32"
PRETTY_NAME="Fedora 32 (Workstation Edition)"
ANSI_COLOR="0;34"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:32"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f32/system-administrators-guide/"
SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=32
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=32
PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
VARIANT="Workstation Edition"
VARIANT_ID=workstation
```

##### STEPS TO REPRODUCE

```
- name: Manage RHEL Subscription for Newly Installed System 
  hosts: servers
  vars_files:
    - secret.yml

  - name: Register RHEL Sub
    redhat_subscription:
        state: present
        username: "example@redhat.com"
        password: "{{ access_redhat_password }}"
        pool_ids: <pool_id>
```
##### EXPECTED RESULTS

The expected result is to have the play fail, and exit with an error saying something along the lines of "privilege escalation is not enabled". 

##### ACTUAL RESULTS

When the above is executed without ```become=true``` , the playbook does not exit with an error.



Discussion:
Files identified in the description:
* [`plugins/modules/packaging/os/redhat_subscription.py`](https://github.com/ansible-collections/community.general/blob/master/plugins/modules/packaging/os/redhat_subscription.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @alikins @barnabycourt @kahowell
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Files identified in the description:
* [`plugins/modules/redhat_subscription.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/redhat_subscription.py)

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->

Resolving patch:
diff --git a/plugins/modules/redhat_subscription.py b/plugins/modules/redhat_subscription.py
--- a/plugins/modules/redhat_subscription.py
+++ b/plugins/modules/redhat_subscription.py
@@ -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
@@ -291,7 +293,7 @@
 '''
 
 from os.path import isfile
-from os import unlink
+from os import getuid, unlink
 import re
 import shutil
 import tempfile
@@ -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']
diff --git a/plugins/modules/rhsm_release.py b/plugins/modules/rhsm_release.py
--- a/plugins/modules/rhsm_release.py
+++ b/plugins/modules/rhsm_release.py
@@ -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:
@@ -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
@@ -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
diff --git a/plugins/modules/rhsm_repository.py b/plugins/modules/rhsm_repository.py
--- a/plugins/modules/rhsm_repository.py
+++ b/plugins/modules/rhsm_repository.py
@@ -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
@@ -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)
@@ -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']


Test patch:
diff --git a/tests/unit/plugins/modules/test_redhat_subscription.py b/tests/unit/plugins/modules/test_redhat_subscription.py
--- a/tests/unit/plugins/modules/test_redhat_subscription.py
+++ b/tests/unit/plugins/modules/test_redhat_subscription.py
@@ -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'])
diff --git a/tests/unit/plugins/modules/test_rhsm_release.py b/tests/unit/plugins/modules/test_rhsm_release.py
--- a/tests/unit/plugins/modules/test_rhsm_release.py
+++ b/tests/unit/plugins/modules/test_rhsm_release.py
@@ -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):