10 Commits

Author SHA1 Message Date
Hideki Saito
ef1937b771 Update README Support section to reference Red Hat Automation Hub (#768)
Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-07-08 08:37:41 +09:00
Hideki Saito
bf4e5d917e Remove meta-runtime[unsupported-version] line from the skip_list (#767)
Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-07-08 08:14:25 +09:00
Hideki Saito
e114652e45 Replace remote test env RHEL9.7 and 10.1 with 9.8 and 10.2 (#763)
- Replace 9.7 with 9.8
- Replace 10.1 with 10.2
- Addresses https://github.com/ansible/ansible/pull/87120

Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-07-01 10:39:34 +09:00
Hideki Saito
18f2f69c53 Fixes the symlink handling issue in the authorized_key module (#760)
- Addresses CVE-2026-11837
- Fixes #759

Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-06-30 08:45:30 +09:00
Hideki Saito
674315f2da Replace AZP remote test FreeBSD-14.2 with 14.3 for Ansible Core 2.19 (#755)
Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-06-09 21:21:39 +09:00
Hideki Saito
f7945c4bc9 [CI] AZP bump test container version to 8.0.0 (#751)
- Bump test container version to 8.0.0 for Ansible Core 2.18+
- Keep using 7.0.0 for Ansible Core 2.16 and 2.17. Both versions don't support Python3.13.

Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-06-01 03:34:12 -07:00
Abhijeet Kasurde
f265682c99 sysctl: Doc update (#745)
* Make documentation more generic

Fixes: #411

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
2026-05-27 08:42:16 +09:00
Abhijeet Kasurde
af933670cc authorized_key: Use loop instead of with_file in example (#740)
Fixes: #607

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
2026-05-24 16:22:50 +09:00
Vladimir Botka
3c232a2429 In FreeBSD, fail if loader.conf shall be reloaded. (#664)
Fix #663
2026-05-20 08:43:23 -07:00
Patrick Kingston
9cd0a1f0ef docs: added attributes metadata for check_mode support (fixes #643) (#741)
Co-authored-by: jkhall81 <jason.kei.hall@gmail.com>
2026-05-21 00:24:37 +09:00
19 changed files with 186 additions and 28 deletions

View File

@@ -4,7 +4,6 @@
# SPDX-FileCopyrightText: 2024, Ansible Project
skip_list:
- meta-runtime[unsupported-version] # This rule doesn't make any sense
- fqcn[deep] # This rule produces false positives for files in tests/unit/plugins/action/fixtures/
- sanity[cannot-ignore] # This rule is skipped to keep backward compatibility with Python 2

View File

@@ -37,8 +37,9 @@ variables:
resources:
containers:
- container: default
image: quay.io/ansible/azure-pipelines-test-container:8.0.0
- container: legacy
image: quay.io/ansible/azure-pipelines-test-container:7.0.0
pool: Standard
stages:
@@ -128,6 +129,7 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
container: legacy
nameFormat: "{0}"
testFormat: 2.17/{0}
targets:
@@ -145,6 +147,7 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
container: legacy
nameFormat: "{0}"
testFormat: 2.16/{0}
targets:
@@ -237,6 +240,7 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
container: legacy
testFormat: 2.17/linux/{0}/1
targets:
- name: Fedora 39
@@ -250,6 +254,7 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
container: legacy
testFormat: 2.16/linux/{0}/1
targets:
- name: Fedora 38
@@ -266,10 +271,10 @@ stages:
parameters:
testFormat: devel/{0}/1
targets:
- name: RHEL 10.1
test: rhel/10.1
- name: RHEL 9.7
test: rhel/9.7
- name: RHEL 10.2
test: rhel/10.2
- name: RHEL 9.8
test: rhel/9.8
- name: FreeBSD 14.4
test: freebsd/14.4
- name: FreeBSD 15.0
@@ -321,8 +326,8 @@ stages:
test: rhel/10.1
- name: RHEL 9.7
test: rhel/9.7
- name: FreeBSD 14.2
test: freebsd/14.2
- name: FreeBSD 14.3
test: freebsd/14.3
- name: FreeBSD 13.5
test: freebsd/13.5
@@ -347,6 +352,7 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
container: legacy
testFormat: 2.17/{0}/1
targets:
- name: RHEL 10.0
@@ -360,6 +366,7 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
container: legacy
testFormat: 2.16/{0}/1
targets:
- name: RHEL 10.1

View File

@@ -14,6 +14,12 @@ parameters:
type: object
default: []
# An optional container resource name to use for the test jobs.
# Defaults to "default" if not specified.
- name: container
type: string
default: default
# An optional format string used to generate the job name.
# - {0} is the name of an item in the targets list.
- name: nameFormat
@@ -43,6 +49,7 @@ parameters:
jobs:
- template: test.yml
parameters:
container: ${{ parameters.container }}
jobs:
- ${{ if eq(length(parameters.groups), 0) }}:
- ${{ each target in parameters.targets }}:

View File

@@ -7,11 +7,17 @@ parameters:
- name: jobs
type: object
# An optional container resource name to use for the test jobs.
# Defaults to "default" if not specified.
- name: container
type: string
default: default
jobs:
- ${{ each job in parameters.jobs }}:
- job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
displayName: ${{ job.name }}
container: default
container: ${{ parameters.container }}
workspace:
clean: all
steps:

View File

@@ -99,7 +99,8 @@ We welcome community contributions to this collection. For more details, see [Co
## Support
See [Communication](#Communication) section.
* Community users can find help through the [Communication](#Communication) section.
* Red Hat Ansible Automation Platform subscribers can request support through [Automation Hub](https://console.redhat.com/ansible/automation-hub/collections/published/ansible/posix/) by using the "Create issue" button on the collection page.
## Release Notes and Roadmap

View File

@@ -0,0 +1,3 @@
---
trivial:
- sysctl - added the attributes section to the module documentation to reflect check_mode support (https://github.com/ansible-collections/ansible.posix/issues/643).

View File

@@ -0,0 +1,3 @@
---
trivial:
- Update Azure Pipelines test container to 8.0.0 and use legacy container for ansible-core 2.16/2.17.

View File

@@ -0,0 +1,3 @@
---
trivial:
- Replace AZP remote test FreeBSD-14.2 with 14.3 for Ansible Core 2.19.

View File

@@ -0,0 +1,2 @@
security_fixes:
- authorized_key - fix local privilege escalation via symlink-following when running as root (https://github.com/ansible-collections/ansible.posix/issues/759).

View File

@@ -0,0 +1,3 @@
---
trivial:
- Replace AZP remote test RHEL9.7 and RHEL10.1 with 9.8 and 10.2 for devel branch.

View File

@@ -0,0 +1,4 @@
---
trivial:
- ansible-lint - Removed ``meta-runtime[unsupported-version]`` from the skip_list in ``.ansible-lint``.
...

View File

@@ -0,0 +1,4 @@
---
bugfixes:
- README - Added ``Red Hat Automation Hub`` as correct contact information for Red Hat Ansible Automation Platform subscribers.
...

View File

@@ -0,0 +1,3 @@
---
bugfixes:
- sysctl - reload sysctl only if the sysctl file is ``/etc/sysctl.conf`` or ``/etc/sysctl.conf.local`` (https://github.com/ansible-collections/ansible.posix/issues/663).

View File

@@ -121,10 +121,10 @@ EXAMPLES = r'''
ansible.posix.authorized_key:
user: deploy
state: present
key: '{{ item }}'
with_file:
- public_keys/doe-jane
- public_keys/doe-john
key: "{{ lookup('file', item) }}"
loop:
- public_keys/doe-jane
- public_keys/doe-john
- name: Set authorized key defining key options
ansible.posix.authorized_key:
@@ -307,6 +307,17 @@ class keydict(dict):
return [item[1] for item in self.items()]
def _safe_open_write(module, path, follow):
flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
if not follow and hasattr(os, 'O_NOFOLLOW'):
flags |= os.O_NOFOLLOW
try:
fd = os.open(path, flags, int('0600', 8))
except OSError as e:
module.fail_json(msg="File open failed %s : %s" % (path, to_native(e)))
return fd
def keyfile(module, user, write=False, path=None, manage_dir=True, follow=False):
"""
Calculate name of authorized keys file, optionally creating the
@@ -359,7 +370,7 @@ def keyfile(module, user, write=False, path=None, manage_dir=True, follow=False)
module.fail_json(msg="Failed to create directory %s : %s" % (sshdir, to_native(e)))
if module.selinux_enabled():
module.set_default_selinux_context(sshdir, False)
os.chown(sshdir, uid, gid)
os.chown(sshdir, uid, gid, follow_symlinks=follow)
os.chmod(sshdir, int('0700', 8))
if not os.path.exists(keysfile):
@@ -367,16 +378,13 @@ def keyfile(module, user, write=False, path=None, manage_dir=True, follow=False)
if not os.path.exists(basedir):
os.makedirs(basedir)
f = None
try:
f = open(keysfile, "w") # touches file so we can set ownership and perms
finally:
f.close()
fd = _safe_open_write(module, keysfile, follow)
os.close(fd)
if module.selinux_enabled():
module.set_default_selinux_context(keysfile, False)
try:
os.chown(keysfile, uid, gid)
os.chown(keysfile, uid, gid, follow_symlinks=follow)
os.chmod(keysfile, int('0600', 8))
except OSError:
pass
@@ -607,7 +615,7 @@ def enforce_state(module, params):
# check current state -- just get the filename, don't create file
do_write = False
params["keyfile"] = keyfile(module, user, do_write, path, manage_dir)
params["keyfile"] = keyfile(module, user, do_write, path, manage_dir, follow)
existing_content = readfile(module, params["keyfile"])
existing_keys = parsekeys(module, existing_content)
@@ -696,6 +704,11 @@ def enforce_state(module, params):
if not module.check_mode:
writefile(module, filename, new_content)
user_entry = pwd.getpwnam(user)
uid = user_entry.pw_uid
gid = user_entry.pw_gid
os.chown(filename, uid, gid, follow_symlinks=follow)
os.chmod(filename, int('0600', 8))
params['changed'] = True
return params

View File

@@ -12,9 +12,12 @@ __metaclass__ = type
DOCUMENTATION = r'''
---
module: sysctl
short_description: Manage entries in sysctl.conf.
short_description: Manage sysctl entries
description:
- This module manipulates sysctl entries and optionally performs a C(/sbin/sysctl -p) after changing them.
- If you are using C(systemd-sysctl(8)), note that it won't use the file C(/etc/sysctl.conf).
- If you are using C(procps) sysctl, it reads C(/etc/sysctl.conf).
- Read more about L(sysctl.conf, https://www.man7.org/linux/man-pages/man5/sysctl.conf.5.html).
version_added: "1.0.0"
options:
name:
@@ -41,14 +44,14 @@ options:
default: false
reload:
description:
- If V(true), performs a C(/sbin/sysctl -p) if the O(sysctl_file) is
updated. If V(false), does not reload C(sysctl) even if the
O(sysctl_file) is updated.
- If V(true), performs a C(/sbin/sysctl -p) if the O(sysctl_file) is updated.
- If V(false), does not reload C(sysctl) even if the O(sysctl_file) is updated.
- For FreeBSD, can not be used with O(sysctl_file) other than C(/etc/sysctl.conf) or C(/etc/sysctl.conf.local).
type: bool
default: true
sysctl_file:
description:
- Specifies the absolute path to C(sysctl.conf), if not C(/etc/sysctl.conf).
- Specifies the absolute path to sysctl file, if not C(/etc/sysctl.conf).
default: /etc/sysctl.conf
type: path
sysctl_set:
@@ -56,6 +59,17 @@ options:
- Verify token value with the sysctl command and set with C(-w) if necessary.
type: bool
default: false
attributes:
check_mode:
support: full
description: Can run in check_mode and return changed status prediction without modifying target.
diff_mode:
support: none
description: Does not support differences output.
platform:
platforms: posix
support: full
description: Supported on POSIX-compliant systems.
author:
- David CHANIAL (@davixx)
'''
@@ -155,6 +169,11 @@ class SysctlModule(object):
self.platform = platform.system().lower()
# system specific tests
freebsd_sysctl_files = ['/etc/sysctl.conf', '/etc/sysctl.conf.local']
if self.platform == 'freebsd' and self.sysctl_file not in freebsd_sysctl_files and self.args['reload']:
self.module.fail_json(msg="%s can not be reloaded. Set reload=False." % self.sysctl_file)
# Whitespace is bad
self.args['name'] = self.args['name'].strip()
self.args['value'] = self._parse_value(self.args['value'])

View File

@@ -0,0 +1,22 @@
---
#
# Check: keysfile is symlink and follow=false
#
- name: Try to add key with keysfile as symlink
ansible.posix.authorized_key:
user: testuser
key: "{{ rsa_key_basic }}"
state: present
manage_dir: false
follow: false
- name: Assert target file ownership unchanged
ansible.builtin.stat:
path: /tmp/symlink_test_target/target_file
register: target_file_stat
- name: Verify target file is still owned by root
ansible.builtin.assert:
that:
- target_file_stat.stat.uid == 0
...

View File

@@ -0,0 +1,12 @@
---
- name: Remove testuser
ansible.builtin.user:
name: testuser
state: absent
remove: true
- name: Remove symlink target directory
ansible.builtin.file:
path: /tmp/symlink_test_target
state: absent
...

View File

@@ -0,0 +1,38 @@
---
- name: Create testuser for symlink tests
ansible.builtin.user:
name: testuser
create_home: true
register: testuser_result
- name: Create symlink target directory
ansible.builtin.file:
path: /tmp/symlink_test_target
state: directory
owner: root
mode: '0700'
- name: Create a target file owned by root
ansible.builtin.copy:
dest: /tmp/symlink_test_target/target_file
content: "sensitive data"
owner: root
mode: '0600'
- name: Remove .ssh directory if exists
ansible.builtin.file:
path: "{{ testuser_result.home }}/.ssh"
state: absent
- name: Create .ssh directory
ansible.builtin.file:
path: "{{ testuser_result.home }}/.ssh"
state: directory
mode: '0700'
- name: Create symlink from authorized_keys to target file
ansible.builtin.file:
src: /tmp/symlink_test_target/target_file
dest: "{{ testuser_result.home }}/.ssh/authorized_keys"
state: link
...

View File

@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
- name: Setup testing environment
- name: Setup for testing environment
ansible.builtin.import_tasks: setup_steps.yml
- name: Test for multiple keys handling
@@ -37,3 +37,12 @@
- name: Test for permission denied files
ansible.builtin.import_tasks: check_permissions.yml
- name: CVE-2026-11837 Setup for symlink tests
ansible.builtin.import_tasks: check_symlink_setup.yml
- name: CVE-2026-11837 Test for symlink tests
ansible.builtin.import_tasks: check_symlink.yml
- name: CVE-2026-11837 Cleanup symlink test
ansible.builtin.import_tasks: check_symlink_cleanup.yml