mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-03-10 11:35:20 +01:00
Compare commits
11 commits
f171313cce
...
917e01066d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
917e01066d | ||
|
|
34f140c22f | ||
|
|
83c4d2abd1 | ||
|
|
e5733c5e49 | ||
|
|
d49bd27fae | ||
|
|
9064ff7eb2 | ||
|
|
a842e5f96a | ||
|
|
97dcdee670 | ||
|
|
55ea4ba1de | ||
|
|
a88f5f8ae0 | ||
|
|
230e5f2a98 |
7 changed files with 70 additions and 7 deletions
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- sysctl - fix sysctl to work properly on symlinks (https://github.com/ansible-collections/ansible.posix/issues/111).
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- synchronize - elevating privileges now works even when `sudo` requires entering the `become_pass`
|
||||||
|
|
@ -580,7 +580,7 @@ Notes
|
||||||
|
|
||||||
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
||||||
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
||||||
- Currently, synchronize is limited to elevating permissions via passwordless sudo. This is because rsync itself is connecting to the remote machine and rsync doesn't give us a way to pass sudo credentials in.
|
- Currently, synchronize is limited to elevating permissions via sudo. This now even works when password entry is required.
|
||||||
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and rsync does not provide us a way to pass a password to the connection.
|
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and rsync does not provide us a way to pass a password to the connection.
|
||||||
- Expect that dest=~/x will be ~<remote_user>/x even if using sudo.
|
- Expect that dest=~/x will be ~<remote_user>/x even if using sudo.
|
||||||
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
||||||
|
|
|
||||||
|
|
@ -391,10 +391,24 @@ class ActionModule(ActionBase):
|
||||||
# If no rsync_path is set, become was originally set, and dest is
|
# If no rsync_path is set, become was originally set, and dest is
|
||||||
# remote then add privilege escalation here.
|
# remote then add privilege escalation here.
|
||||||
if self._play_context.become_method == 'sudo':
|
if self._play_context.become_method == 'sudo':
|
||||||
if self._play_context.become_user:
|
|
||||||
rsync_path = 'sudo -u %s rsync' % self._play_context.become_user
|
# if become is set, we can either rely on passwordless sudo or pass the password
|
||||||
|
if self._play_context.become_pass is None:
|
||||||
|
rsync_path = 'sudo '
|
||||||
else:
|
else:
|
||||||
rsync_path = 'sudo rsync'
|
# pass the become password using the environment so that the synchronize module
|
||||||
|
# can wrap ssh on the host with a shell script that injects the password into
|
||||||
|
# stdin, allowing for `sudo -S` on the target machine to retrieve the password
|
||||||
|
if hasattr(self._task, 'environment'):
|
||||||
|
self._task.environment = []
|
||||||
|
self._task.environment.append({'BECOME_PASS': self._play_context.become_pass})
|
||||||
|
_tmp_args['_ssh_wrapper'] = True
|
||||||
|
rsync_path = 'sudo -S '
|
||||||
|
|
||||||
|
if self._play_context.become_user:
|
||||||
|
rsync_path += '-u %s rsync' % self._play_context.become_user
|
||||||
|
else:
|
||||||
|
rsync_path += 'rsync'
|
||||||
# TODO: have to add in the rest of the become methods here
|
# TODO: have to add in the rest of the become methods here
|
||||||
|
|
||||||
# We cannot use privilege escalation on the machine running the
|
# We cannot use privilege escalation on the machine running the
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ notes:
|
||||||
delegate_to host when delegate_to is used).
|
delegate_to host when delegate_to is used).
|
||||||
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
||||||
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
||||||
- Currently, synchronize is limited to elevating permissions via passwordless sudo. This is because rsync itself is connecting to the remote machine
|
- Currently, synchronize is limited to elevating permissions via sudo. This now even works when password entry is required.
|
||||||
and rsync doesn't give us a way to pass sudo credentials in.
|
and rsync doesn't give us a way to pass sudo credentials in.
|
||||||
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been
|
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been
|
||||||
determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and
|
determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and
|
||||||
|
|
@ -432,6 +432,7 @@ def main():
|
||||||
_ssh_args=dict(type='str'),
|
_ssh_args=dict(type='str'),
|
||||||
use_ssh_args=dict(type='bool', default=False),
|
use_ssh_args=dict(type='bool', default=False),
|
||||||
ssh_connection_multiplexing=dict(type='bool', default=False),
|
ssh_connection_multiplexing=dict(type='bool', default=False),
|
||||||
|
_ssh_wrapper=dict(type='bool', default=False),
|
||||||
partial=dict(type='bool', default=False),
|
partial=dict(type='bool', default=False),
|
||||||
verify_host=dict(type='bool', default=False),
|
verify_host=dict(type='bool', default=False),
|
||||||
delay_updates=dict(type='bool', default=True),
|
delay_updates=dict(type='bool', default=True),
|
||||||
|
|
@ -474,6 +475,7 @@ def main():
|
||||||
rsync_opts = module.params['rsync_opts']
|
rsync_opts = module.params['rsync_opts']
|
||||||
ssh_args = module.params['_ssh_args']
|
ssh_args = module.params['_ssh_args']
|
||||||
ssh_connection_multiplexing = module.params['ssh_connection_multiplexing']
|
ssh_connection_multiplexing = module.params['ssh_connection_multiplexing']
|
||||||
|
ssh_wrapper = module.params['_ssh_wrapper']
|
||||||
verify_host = module.params['verify_host']
|
verify_host = module.params['verify_host']
|
||||||
link_dest = module.params['link_dest']
|
link_dest = module.params['link_dest']
|
||||||
delay_updates = module.params['delay_updates']
|
delay_updates = module.params['delay_updates']
|
||||||
|
|
@ -568,6 +570,13 @@ def main():
|
||||||
ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd)
|
ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd)
|
||||||
if ssh_args:
|
if ssh_args:
|
||||||
ssh_cmd_str += ' %s' % ssh_args
|
ssh_cmd_str += ' %s' % ssh_args
|
||||||
|
# When `become: yes` is set but the account on the target requires a password for sudo, we have to supply
|
||||||
|
# it from the host side by wrapping the remote shell and inserting the password into stdin.
|
||||||
|
# In the ActionPlugin, the password is assigned to the BECOME_PASS environment variable, so we will not have
|
||||||
|
# to make it visible if anyone logs the command issued by ansible.
|
||||||
|
# Adapted from https://askubuntu.com/a/1263657
|
||||||
|
if ssh_wrapper:
|
||||||
|
ssh_cmd_str = '/bin/sh -c "{ echo $BECOME_PASS; cat - ; } | ' + ssh_cmd_str + ' $0 $* &"'
|
||||||
cmd.append('--rsh=%s' % shlex_quote(ssh_cmd_str))
|
cmd.append('--rsh=%s' % shlex_quote(ssh_cmd_str))
|
||||||
|
|
||||||
if rsync_path:
|
if rsync_path:
|
||||||
|
|
|
||||||
|
|
@ -366,7 +366,7 @@ class SysctlModule(object):
|
||||||
# Completely rewrite the sysctl file
|
# Completely rewrite the sysctl file
|
||||||
def write_sysctl(self):
|
def write_sysctl(self):
|
||||||
# open a tmp file
|
# open a tmp file
|
||||||
fd, tmp_path = tempfile.mkstemp('.conf', '.ansible_m_sysctl_', os.path.dirname(self.sysctl_file))
|
fd, tmp_path = tempfile.mkstemp('.conf', '.ansible_m_sysctl_', os.path.dirname(os.path.realpath(self.sysctl_file)))
|
||||||
f = open(tmp_path, "w")
|
f = open(tmp_path, "w")
|
||||||
try:
|
try:
|
||||||
for l in self.fixed_lines:
|
for l in self.fixed_lines:
|
||||||
|
|
@ -377,7 +377,7 @@ class SysctlModule(object):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# replace the real one
|
# replace the real one
|
||||||
self.module.atomic_move(tmp_path, self.sysctl_file)
|
self.module.atomic_move(tmp_path, os.path.realpath(self.sysctl_file))
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
|
|
|
||||||
|
|
@ -332,3 +332,37 @@
|
||||||
that:
|
that:
|
||||||
- sysctl_invalid_set1 is failed
|
- sysctl_invalid_set1 is failed
|
||||||
- "'vm.mmap_rnd_bits' not in sysctl_invalid_conf_content.stdout"
|
- "'vm.mmap_rnd_bits' not in sysctl_invalid_conf_content.stdout"
|
||||||
|
|
||||||
|
# Test sysctl: sysctl_file is symlink
|
||||||
|
- name: Create link source
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
# Testing Ansible Sysctl module on symlink.
|
||||||
|
dest: /tmp/ansible_sysctl_test.conf
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Create symlink to the conf file
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: /tmp/ansible_sysctl_test.conf
|
||||||
|
dest: /tmp/ansible_sysctl_test_symlink.conf
|
||||||
|
state: link
|
||||||
|
|
||||||
|
- name: Use sysctl module with symlink sysctl file
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: 'kernel.randomize_va_space'
|
||||||
|
value: '1'
|
||||||
|
sysctl_file: /tmp/ansible_sysctl_test_symlink.conf
|
||||||
|
state: present
|
||||||
|
sysctl_set: false
|
||||||
|
reload: false
|
||||||
|
|
||||||
|
- name: Stat sysctl file
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /tmp/ansible_sysctl_test_symlink.conf
|
||||||
|
register: stat_result
|
||||||
|
|
||||||
|
- name: Ensure the sysctl file remains a symlink
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- stat_result.stat.islnk is defined and stat_result.stat.islnk
|
||||||
|
- stat_result.stat.lnk_source == '/tmp/ansible_sysctl_test.conf'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue