10 Commits

Author SHA1 Message Date
Hideki Saito
73939ba8ff Update README Support section to reference Red Hat Automation Hub (#768) (#770)
Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-07-08 15:11:56 +09:00
Hideki Saito
2504f532b8 Remove meta-runtime[unsupported-version] line from the skip_list (#767) (#769)
Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-07-08 11:43:37 +09:00
Hideki Saito
4ac4603af5 Release 2.2.1 commit (#765)
2.2.1 release

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

Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-07-01 12:30:27 +09:00
Hideki Saito
ee1461f46c Replace remote test env RHEL9.7 and 10.1 with 9.8 and 10.2 (#764)
- 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 11:56:25 +09:00
Hideki Saito
78fb77c8d5 Replace AZP remote test FreeBSD-14.2 with 14.3 for Ansible Core 2.19 (#755) (#756)
(cherry picked from commit 674315f2da)

Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-06-10 12:54:21 +09:00
Hideki Saito
d4ac6f63f4 [CI] AZP bump test container version to 8.0.0 (#751) (#752)
- 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.


(cherry picked from commit f7945c4bc9)

Signed-off-by: Hideki Saito <saito@fgrep.org>
2026-06-02 10:04:19 +09:00
Hideki Saito
b42cbb2a97 authorized_key: Use loop instead of with_file in example (#740) (#749)
Fixes: #607


(cherry picked from commit af933670cc)

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2026-05-27 17:01:01 +09:00
Hideki Saito
aaacdb9d13 In FreeBSD, fail if loader.conf shall be reloaded. (#664) (#748)
Fix #663

(cherry picked from commit 3c232a2429)

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
2026-05-27 15:45:16 +09:00
Hideki Saito
955acdca44 docs: added attributes metadata for check_mode support (fixes #643) (#741) (#747)
(cherry picked from commit 9cd0a1f0ef)

Co-authored-by: Patrick Kingston <66141901+pkingstonxyz@users.noreply.github.com>
Co-authored-by: jkhall81 <jason.kei.hall@gmail.com>
2026-05-27 14:18:58 +09:00
16 changed files with 208 additions and 24 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

@@ -4,6 +4,27 @@ ansible.posix Release Notes
.. contents:: Topics
v2.2.1
======
Release Summary
---------------
This is the minor release of the ``ansible.posix`` collection.
This changelog contains all changes to the modules and plugins
in the stable-2 branch that have been added after the release of
``ansible.posix`` 2.2.0
Security Fixes
--------------
- authorized_key - fix local privilege escalation via symlink-following when running as root (https://github.com/ansible-collections/ansible.posix/issues/759).
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).
v2.2.0
======

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

@@ -578,3 +578,27 @@ releases:
- firewalld_info_warnings.yml
- patch_removed.yml
release_date: '2026-05-18'
2.2.1:
changes:
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).
release_summary: 'This is the minor release of the ``ansible.posix`` collection.
This changelog contains all changes to the modules and plugins
in the stable-2 branch that have been added after the release of
``ansible.posix`` 2.2.0'
security_fixes:
- authorized_key - fix local privilege escalation via symlink-following when
running as root (https://github.com/ansible-collections/ansible.posix/issues/759).
fragments:
- 2.2.1.yml
- 643-sysctl-docs.yml
- 751_ci_test_container_update.yml
- 755_ci_test_container_update.yml
- 759_cve_2026_11837.yml
- 763_ci_azp_update_devel.yml
- freebsd_sysctl.yml
release_date: '2026-07-01'

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

@@ -1,7 +1,7 @@
---
namespace: ansible
name: posix
version: 2.2.0
version: 2.2.1
readme: README.md
authors:
- Ansible (github.com/ansible)

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

@@ -44,6 +44,7 @@ options:
- 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:
@@ -56,6 +57,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 +167,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