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

Bugfix/1542/zos script permissions #1852

Draft
wants to merge 8 commits into
base: dev
Choose a base branch
from
Draft
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
34 changes: 23 additions & 11 deletions plugins/modules/zos_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@
- All local scripts copied to a remote z/OS system will be removed from the
managed node before the module finishes executing.
- Execution permissions for the group assigned to the script will be
added to remote scripts. The original permissions for remote scripts will
be restored by the module before the task ends.
added to remote scripts if they are missing. The original permissions
for remote scripts will be restored by the module before the task ends.
- The module will only add execution permissions for the file owner.
- If executing REXX scripts, make sure to include a newline character on
each line of the file. Otherwise, the interpreter may fail and return
Expand Down Expand Up @@ -336,6 +336,7 @@ def run_module():
executable = module.params.get('executable')
creates = module.params.get('creates')
removes = module.params.get('removes')
script_permissions = None

if creates and os.path.exists(creates):
result = dict(
Expand All @@ -358,13 +359,23 @@ def run_module():
msg='The given chdir {0} does not exist on the system.'.format(chdir)
)

# Adding owner execute permissions to the script.
# The module will fail if the Ansible user is not the owner!
script_permissions = os.lstat(script_path).st_mode
os.chmod(
script_path,
script_permissions | stat.S_IXUSR
)
# Checking if current user has permission to execute the script.
# If not, we'll try to set execution permissions if possible.
if not os.access(script_path, os.X_OK):
# Adding owner execute permissions to the script.
# The module will fail if the Ansible user is not the owner!
try:
script_permissions = os.lstat(script_path).st_mode
os.chmod(
script_path,
script_permissions | stat.S_IXUSR
)
except PermissionError:
module.fail_json(
msg='User running Ansible does not have permission to run script {0}.'.format(
script_path
)
)

if executable:
cmd_str = "{0} {1}".format(executable, cmd_str)
Expand All @@ -387,8 +398,9 @@ def run_module():
stderr_lines=stderr.split('\n'),
)

# Reverting script's permissions.
os.chmod(script_path, script_permissions)
# Reverting script's permissions when needed.
if script_permissions:
os.chmod(script_path, script_permissions)

if script_rc != 0 or stderr:
result['msg'] = 'The script terminated with an error'
Expand Down
54 changes: 54 additions & 0 deletions tests/functional/modules/test_zos_script_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import pytest
__metaclass__ = type

from ibm_zos_core.tests.helpers.users import ManagedUserType, ManagedUser


# Using || to concatenate strings without extra spaces.
REXX_SCRIPT_ARGS = """/* REXX */
Expand Down Expand Up @@ -411,3 +413,55 @@ def test_python_script_with_stderr(ansible_zos_module):
finally:
if os.path.exists(script_path):
os.remove(script_path)


def managed_user_create_script(ansible_zos_module):
"""Creates a file using the user set up in ansible_zos_module."""
hosts = ansible_zos_module
msg = "Success"
rexx_script = create_script_content(msg, 'rexx')
local_script = create_local_file(rexx_script, 'rexx')

# Using zos_copy instead of doing an echo with shell to avoid trouble
# with how single quotes are handled.
script_path = '/tmp/zos_script_test_script'
copy_result = hosts.all.zos_copy(
src=local_script,
dest=script_path,
mode='600'
)
for result in copy_result.contacted.values():
assert result.get('changed') is True


def test_super_user_run_script_from_another_user(ansible_zos_module, z_python_interpreter):
hosts = ansible_zos_module
managed_user = None
script_path = '/tmp/zos_script_test_script'

try:
managed_user = ManagedUser.from_fixture(
hosts,
z_python_interpreter
)
managed_user.execute_managed_user_test(
managed_user_test_case="managed_user_create_script",
debug=True,
verbose=True,
managed_user_type=ManagedUserType.ZOS_LIMITED_HLQ
)

zos_script_result = hosts.all.zos_script(
cmd=script_path,
remote_src=True
)

for result in zos_script_result.contacted.values():
assert result.get('changed') is True
assert result.get('failed', False) is False
assert result.get('rc') == 0
assert result.get('stdout', '').strip() == msg
assert result.get('stderr', '') == ''
finally:
hosts.all.file(path=script_path, state="absent")
managed_user.delete_managed_user()
2 changes: 1 addition & 1 deletion tests/helpers/ztest.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def from_args(cls, src):

environment_vars = dict()
environment_vars.update({'_BPXK_AUTOCVT': 'ON'})
environment_vars.update({'_CEE_RUNOPTS': '\'FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)\''})
environment_vars.update({'_CEE_RUNOPTS': 'FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)'})
environment_vars.update({'_TAG_REDIR_IN': 'txt'})
environment_vars.update({'_TAG_REDIR_OUT': 'txt'})
environment_vars.update({'LANG': 'C'})
Expand Down
Loading