Compare commits

...

38 Commits

Author SHA1 Message Date
Thomas Woerner
ef73a85320 Merge pull request #1357 from jangel97/hotfix_sssd_dns_over_tls
ipaclient: Fix AttributeError by defaulting dns_over_tls to False
2025-05-21 17:12:15 +02:00
Jose Angel Morena
5b3a4729f0 ipaclient: Fix AttributeError by defaulting dns_over_tls to False
This change addresses https://github.com/freeipa/ansible-freeipa/issues/1356#issuecomment-2891804763 by explicitly setting `options.dns_over_tls = False` to ensure the attribute is always defined when running ipaclient ansible role.

On RHEL 9 systems (or any environment where `ipasssd_enable_dns_updates: true`), the `ipaclient` python module references `dns_over_tls` without first checking its existence, which results in the following `AttributeError: 'installer_obj' object has no attribute 'dns_over_tls'`:

  TASK \[freeipa.ansible\_freeipa.ipaclient : Install - Configure SSSD] \*\*\*\*\*\*\*\*\*\*\*\*
  An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError:
  'installer\_obj' object has no attribute 'dns\_over\_tls'
  fatal: \[vm-test-rhel9]: FAILED! => {"changed": false, "module\_stderr": "Traceback (most recent call last):\n  File "
 <stdin>", line 107, in <module>\n  File "<stdin>", line 99, in \_ansiballz\_main\n  File "<stdin>", line 47, in invoke\_module\n
  File "/usr/lib64/python3.9/runpy.py", line 225, in run\_module\n    return \_run\_module\_code(code, init\_globals,
  run\_name, mod\_spec)\n  File "/usr/lib64/python3.9/runpy.py", line 97, in \_run\_module\_code\n    \_run\_code(code,
  mod\_globals, init\_globals,\n  File "/usr/lib64/python3.9/runpy.py", line 87, in \_run\_code\n    exec(code, run\_globals)\n
  File "/tmp/ansible\_freeipa.ansible\_freeipa.ipaclient\_setup\_sssd\_payload\_zkyct7sn/ansible\_freeipa.ansible\_freeipa.ipacli. ent\_setup\_sssd\_payload.zip/ansible\_collections/freeipa/ansible\_freeipa/plugins/modules/ipaclient\_setup\_sssd.py",
  line 190, in <module>\n  File "/tmp/ansible\_freeipa.ansible\_freeipa.ipaclient\_setup\_sssd\_payload\_zkyct7sn/ansible\_freeipa.ansible\_freeipa.ipacli. ent\_setup\_sssd\_payload.zip/ansible\_collections/freeipa/ansible\_freeipa/plugins/modules/ipaclient\_setup\_sssd.py",
  line 181, in main\n  File "/usr/lib/python3.9/site-packages/ipaclient/install/client.py", line 1005, in configure\_sssd\_conf\n
  if options.dns\_over\_tls:\nAttributeError: 'installer\_obj' object has no attribute 'dns\_over\_tls'\n", "module\_stdout": "",
  "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

To prevent this, the attribute `options.dns_over_tls` is now initialised to false in `roles/ipaclient/library/ipaclient_setup_sssd.py`.This fix is inspired by a similar pattern in [[PR #1340](https://github.com/freeipa/ansible-freeipa/pull/1340/files)](https://github.com/freeipa/ansible-freeipa/pull/1340/files).

This failure has been observed in versions `1.14.6` and `1.14.5` of the [ansible_freeipa collection](https://galaxy.ansible.com/ui/repo/published/freeipa/ansible_freeipa/) from Ansible Galaxy.

Signed-off-by: Jose Angel Morena <jmorenas@redhat.com>
2025-05-21 15:38:52 +02:00
Rafael Guterres Jeffman
7245339934 Merge pull request #1351 from t-woerner/infra_image_start_debug
infra/image/shdefaults: Add SYS_PTRACE to CAP_DEFAULTS
2025-04-17 11:53:02 -03:00
Thomas Woerner
638422e113 infra/image/shcontainer: Fix processing of multi item CAP_DEFAULTS
readarray expects to get an item per line to be added to the array.

Printing one item per line with printf fixes this to get the proper
formatting for "${CAP_DEFAULTS[@]}" as a valid input for readarray.
2025-04-17 16:46:12 +02:00
Thomas Woerner
432376524c infra/image/shdefaults: Add SYS_PTRACE to CAP_DEFAULTS
Debugging is now enabled by default in the containers that are
generated with container_create. "+SYS_PTRACE" has been added to
CAP_DEFAULTS in shdefaults for this.
2025-04-17 15:00:39 +02:00
Thomas Woerner
86701caf8b Merge pull request #1350 from freeipa/remove_pkg_resources
ipareplica: Don't rely on pkg_resources whenever possible
2025-04-17 14:50:43 +02:00
Thomas Woerner
d1857c18ac Merge pull request #1352 from freeipa/fix_sssd_on_test_container
test container: Add DAC_READ_SEARCH capability
2025-04-17 14:49:49 +02:00
Thomas Woerner
edbdd3af79 Merge pull request #1348 from abbra/fix-cert-iteration
Fix CA certificates iteration
2025-04-17 14:48:51 +02:00
Rafael Guterres Jeffman
2d3da2d72c test container: Add DAC_READ_SEARCH capability
SSSD 2.10+ runs under non-privileged user 'sssd' and relies on system
capabilities to get access to certain resources like /etc/krb5.keytab.
Not having these capabilities result in SSSD not starting.

Podman has reduced the capabilities granted to containers, and to be
able to start SSSD it is needed to add DAC_READ_SEARCH back.

This patch adds file infra/images/shdefaults to store the defaults used
by ansible-freeipa shell utilities in a contral location.

See:  https://github.com/containers/podman/discussions/24904#discussioncomment-11718823

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-04-17 09:44:01 -03:00
Thomas Woerner
329c16f742 Merge pull request #1355 from freeipa/fix_container_tee_message
infra/image/shcontainer: Fix log message in container_tee
2025-04-17 14:15:50 +02:00
Rafael Guterres Jeffman
66c0be06d0 infra/image/shcontainer: Fix log message in container_tee
Fix a log message in function container_tee and quote the temporary
filename.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-04-16 16:25:29 -03:00
Rafael Guterres Jeffman
f04c90f4db Merge pull request #1354 from t-woerner/extended_infra_image_container_functions
infra/image/shcontainer: Volume support and new container_tee
2025-04-16 12:06:10 -03:00
Thomas Woerner
dfa4bcb68f infra/image/shcontainer: Volume support and new container_tee
This change adds support for volumes to container_create. Now it can be
used like in this example:

    container_create "${name}" "${local_image}" "hostname=${hostname}" \
        "${capabilities:+capabilities=$capabilities}" \
        volume=$PWD:/root/src

The new function container_tee has been added to enable creation of
fiiles with content from stdin like in this example:

    cat <<EOF | container_tee "${name}" "/root/.gdbinit"
    set debuginfod enabled on
    set follow-fork-mode child
    EOF
2025-04-16 16:11:14 +02:00
Rafael Guterres Jeffman
b1328ba7d5 ipareplica: Don't rely on pkg_resources whenever possible
Python's module "pkg_resources" API has been deprecated in Python 3.12
and will be removed in a future release, and recent FreeIPA versions
provide a replacement for pkg_resources.parse_version.

To remove ansible-freeipa dependency on pkg_resources and not add a
dependency on the 'packaging' module, which is not available in the
standard Python distribution, we'll try to import the funcion used in
FreeIPA to parse versions, and fallback to pkg_resources when it fails.

As an equivalent class is needed, a fallback function is not provided
and execution will fail if neither the FreeIPA nor the pkg_resources
parse_version function are available.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-04-08 11:31:05 -03:00
Rafael Guterres Jeffman
fe58f3a8ba Merge pull request #1301 from t-woerner/try_ubuntu_24.04_1
Use ubuntu 24.04 for testing
2025-04-02 12:30:43 -03:00
Thomas Woerner
4dc6192640 infra/image/shcontainer: Ensure '/ect/shadow' is readable
The shadow file in a Fedora or CentOS Stream container is not readable
any more using Ubuntu 24.04.

An extra call to ensure that the shadow file is readable again has been
added to container_start.
2025-04-02 17:21:35 +02:00
Thomas Woerner
e9435410b2 utils/setup_test_container.sh: Wait till systemd-journald is running
This ensures that systemctl list-jobs could be executed and it will
be waited till the list of jobs is empty.
2025-04-02 17:21:35 +02:00
Thomas Woerner
de6a0429a0 Merge pull request #1349 from freeipa/fix_flake8_7_2_0
Fix flake8 7 2 0
2025-04-02 17:10:18 +02:00
Rafael Guterres Jeffman
40d85f83e4 Fix linter issues related to 'global'
This patch fixes an issue reported by flake8 7.2.0 and enables a pylint
test that was disable, both related to the use of 'global'.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-04-02 11:59:30 -03:00
Rafael Guterres Jeffman
678927f35c Unpin flake8 version from requirements-dev.txt
Upstream flake8 lint test is executed with the latest available version
in pip, but the requirements-dev.txt had a pinned version, making flake8
error to be found too late.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-04-02 11:56:47 -03:00
Rafael Guterres Jeffman
f0e6d0c89f pre-commit: Bump flake8 version to 7.2.0
Bump pre-commit version to the latest available.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-04-02 11:55:19 -03:00
Thomas Woerner
c095c24950 Use ubuntu 24.04 for testing 2025-04-02 12:55:23 +02:00
Alexander Bokovoy
34dc75802c Fix CA certificates iteration
FreeIPA fix for https://pagure.io/freeipa/issue/9652 now produces five
elements tuple when iterating over CA certificate list, the last element
being the serial number. We do not need it, so extract only the first
four elements (certificate, nickname, trusted, EKU).

The regression was introduced by FreeIPA commit
f91b677ada376034b25d50e78475237c5976770e.

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
2025-03-30 13:01:35 +03:00
Varun Mylaraiah
feb33e4e3a Merge pull request #1340 from t-woerner/dns_over_tls_hotfix
ipa* deployment roles: Hotfix for dns_over_tls (Freeipa#7343)
2025-02-11 14:51:58 +05:30
Thomas Woerner
3c50a8121f ipa* deployment roles: Hotfix for dns_over_tls (Freeipa#7343)
This is a hotfix to allow deployments of clients, replicas and servers
with the dns_over_tls PR for freeipa: https://github.com/freeipa/freeipa/pull/7343/

ipaclient: client.update_ssh_keys has changed parameters,
options.dns_over_tls needs to be set for ipaclient_setup_nss.

ipareplica, ipaserver: Set new parameters globally in module_utils so
far: options.dns_over_tls, options.dns_over_tls_key, options.dns_over_tls_cert,
options.dot_forwarders and options.dns_policy.

The enablement for DNS over TLS for the deployment roles will be done later on.
2025-02-07 18:16:10 +01:00
Rafael Guterres Jeffman
e8688d4cf5 Merge pull request #1337 from t-woerner/ipagroup_fix_externalmember_client_context_fail
ipagroup: Fix test for externalmember use in client context
2025-02-04 11:54:15 -03:00
Thomas Woerner
d540be425a ipagroup: Fix test for externalmember use in client context
The test has been changed with the management fix for AD objects. The
conditional was lacking brackets and therefore did not properly work.
The brackets have been added.

Related: https://issues.redhat.com/browse/RHEL-70023
2025-02-04 12:32:42 +01:00
Thomas Woerner
c1d7ed1df6 Merge pull request #1335 from rjeffman/ipagroup_fix_1
ipagroup: Fix management of AD objects
2025-02-03 13:43:35 +01:00
Thomas Woerner
0fc8ddf450 Merge pull request #1327 from rjeffman/remove_unsupported_systems
Remove 'vars' files of unsupported distributions
2025-02-03 12:58:16 +01:00
Rafael Guterres Jeffman
012f0deb00 Remove 'vars' files of unsupported distributions
This patch removes 'vars' files from roles for unsupported distributions
and change minimum supported Fedora to version 40+.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-01-31 12:45:45 -03:00
Thomas Woerner
f27b0e3011 Merge pull request #1334 from rjeffman/update_c10s_image
Update c10s image
2025-01-31 16:03:32 +01:00
Rafael Guterres Jeffman
8b4b22dd00 Use non-development CentOS 10 Stream image
As the official, non-development, CentOS 10 Stream image is available,
ansible-freeipa tests must use it instead of the centos-development one.
2025-01-31 11:32:59 -03:00
Rafael Guterres Jeffman
91c4b83311 Configure yamllint to be compatible with ansible-lint
Current version of ansible-list pre-commit hook required changes in the
ansible-freeipa yamllint configuration and these changes triggered
issues in the current playbooks on roles and tests.

This patch adds the required changes to yaml lint configuration and
fixes the affected playbooks.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-01-31 11:32:59 -03:00
Rafael Guterres Jeffman
6925503a10 ipagroup: Fix management of AD objects
When using AD objects, a user expects to use the more human readable
form, like "user@ad.domain", but this impose some dificulties on
evaluating which object is being referenced as AD has several forms to
refer to the same object.

Each object is AD is identified uniquely by its SID, and this is the
identifier that IPA stores in its database. When managing AD objects,
IPA finds its SID and works with that value.

ansible-freeipa tried to process these objects using the human readable
values, and it cause idempontence error when ensuring the values were
present or modified, and, at least in some cases, prevented the objects
to be made absent, as the object list created didn't match the SID to
the value used as module parameter.

By using SID to process the AD objects in ipagroup, the addition or
removal of members works and idempotence of these members is ensured.

The only issue with thils approach is that it only works no server
nodes. In client nodes, the conversion to SID is not available and the
same issues that existed before will still be present.

Tests were updated to reflect these changes, a new test, specific to
idempotence issues of AD objects was added:

   tests/group/test_group_ad_users.yml

Resolves: https://issues.redhat.com/browse/RHEL-70023
2025-01-31 10:29:48 -03:00
Thomas Woerner
0da0b22ae7 Merge pull request #1336 from rjeffman/idoverrideuser_client_context_test
tests/idoverrideuser: Fix client context test when running on client
2025-01-31 13:00:32 +01:00
Rafael Guterres Jeffman
f5f454915c tests/idoverrideuser: Fix client context test when running on client
When running test_idoverrideuser_client_context.yml on a client host, it
tried to run a task that does not have the required fields and fails
the test.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-01-29 00:56:56 -03:00
Rafael Guterres Jeffman
8581b79eba tests: Improve FreeIPA facts
This patch improves tests/env_freeipa_facts.yml by ensuring
ipaserver_realm is set, making AD server availability discoverable, and
allowing playbooks to run with 'gather_facts: false' by gathering
minimal facts.
2025-01-29 00:41:38 -03:00
Rafael Guterres Jeffman
a9602431ce ansible_freeipa_module_utils: Add functions to handle objects SID
When managing AD objects the SID of the objects are stored in FreeIPA
database, but a user would still use the human readable values, like
"AD\\user" or "user@ad.domain". This can cause idempotence issues in
many cases, and prevent some actions to be performed, like ensure
absence of the object.

The methods added allow the conversion of one or multiple objects, and
will be used by any module that manages AD objects.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-01-29 00:41:38 -03:00
63 changed files with 526 additions and 267 deletions

View File

@@ -26,7 +26,7 @@ repos:
- id: yamllint
files: \.(yaml|yml)$
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
rev: 7.2.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/pylint

View File

@@ -20,4 +20,9 @@ rules:
max: 160
# Disabled rules
indentation: disable
comments: disable
comments:
min-spaces-from-content: 1
comments-indentation: disable
octal-values:
forbid-implicit-octal: true
forbid-explicit-octal: true

View File

@@ -8,8 +8,12 @@ The group module allows to ensure presence and absence of groups and members of
The group module is as compatible as possible to the Ansible upstream `ipa_group` module, but additionally offers to add users to a group and also to remove users from a group.
## Note
Ensuring presence (adding) of several groups with mixed types (`external`, `nonposix` and `posix`) requires a fix in FreeIPA. The module implements a workaround to automatically use `client` context if the fix is not present in the target node FreeIPA and if more than one group is provided to the task using the `groups` parameter. If `ipaapi_context` is forced to be `server`, the module will fail in this case.
Notes
-----
* Ensuring presence (adding) of several groups with mixed types (`external`, `nonposix` and `posix`) requires a fix in FreeIPA. The module implements a workaround to automatically use `client` context if the fix is not present in the target node FreeIPA and if more than one group is provided to the task using the `groups` parameter. If `ipaapi_context` is forced to be `server`, the module will fail in this case.
* Using `externalmember` or `idoverrideuser` is only supported with `ipaapi_context: server`. With 'client' context, module execution will fail.
Features
@@ -213,7 +217,7 @@ Example playbook to add members from a trusted realm to an external group:
---
- name: Playbook to handle groups.
hosts: ipaserver
tasks:
- name: Create an external group and add members from a trust to it.
ipagroup:
@@ -276,6 +280,7 @@ Example playbook to ensure groups are absent:
state: absent
```
Variables
=========
@@ -299,8 +304,8 @@ Variable | Description | Required
`service` | List of service name strings assigned to this group. Only usable with IPA versions 4.7 and up. | no
`membermanager_user` | List of member manager users assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
`membermanager_group` | List of member manager groups assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
`externalmember` \| `ipaexternalmember` \| `external_member`| List of members of a trusted domain in DOM\\name or name@domain form. | no
`idoverrideuser` | List of user ID overrides to manage. Only usable with IPA versions 4.8.7 and up.| no
`externalmember` \| `ipaexternalmember` \| `external_member`| List of members of a trusted domain in DOM\\name or name@domain form. Requires "server" context. | no
`idoverrideuser` | List of user ID overrides to manage. Only usable with IPA versions 4.8.7 and up. Requires "server" context. | no
`rename` \| `new_name` | Rename the user object to the new name string. Only usable with `state: renamed`. | no
`action` | Work on group or member level. It can be on of `member` or `group` and defaults to `group`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | yes

View File

@@ -66,7 +66,7 @@ Supported Distributions
-----------------------
* RHEL/CentOS 7.4+
* Fedora 26+
* Fedora 40+
* Ubuntu
* Debian 10+ (ipaclient only, no server or replica!)
@@ -125,7 +125,7 @@ ansible-freeipa/plugins/module_utils to ~/.ansible/plugins/
**RPM package**
There are RPM packages available for Fedora 29+. These are installing the roles and modules into the global Ansible directories for `roles`, `plugins/modules` and `plugins/module_utils` in the `/usr/share/ansible` directory. Therefore is it possible to use the roles and modules without adapting the names like it is done in the example playbooks.
There are RPM packages available for Fedora. These are installing the roles and modules into the global Ansible directories for `roles`, `plugins/modules` and `plugins/module_utils` in the `/usr/share/ansible` directory. Therefore is it possible to use the roles and modules without adapting the names like it is done in the example playbooks.
**Ansible Galaxy**

View File

@@ -3,7 +3,7 @@ trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
vmImage: 'ubuntu-24.04'
variables:
ansible_version: "-core >=2.16,<2.17"

View File

@@ -10,7 +10,7 @@ schedules:
trigger: none
pool:
vmImage: 'ubuntu-20.04'
vmImage: 'ubuntu-24.04'
variables:
# We need to have two sets, as c8s is not supported by all ansible versions

View File

@@ -3,7 +3,7 @@ trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
vmImage: 'ubuntu-24.04'
variables:
distros: "fedora-latest,c10s,c9s,c8s,fedora-rawhide"

View File

@@ -1,4 +1,4 @@
FROM quay.io/centos/centos:stream10-development
FROM quay.io/centos/centos:stream10
ENV container=podman
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \

View File

@@ -4,13 +4,20 @@
SCRIPTDIR="$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")"
TOPDIR="$(readlink -f "${SCRIPTDIR}/../..")"
# shellcheck disable=SC1091
. "${SCRIPTDIR}/shdefaults"
# shellcheck disable=SC1091
. "${TOPDIR}/utils/shfun"
container_create() {
local name=${1}
local image=${2}
shift 2
declare -a extra_opts=()
declare -a extra_opts
readarray -t extra_opts < \
<(sed -e "s/-/--cap-drop=/g" -e "s/+/--cap-add=/g" \
<<< "$(printf '%s\n' "${CAP_DEFAULTS[@]}")")
for opt in "$@"
do
[ -z "${opt}" ] && continue
@@ -19,6 +26,7 @@ container_create() {
cpus=*) extra_opts+=("--${opt}") ;;
memory=*) extra_opts+=("--${opt}") ;;
capabilities=*) extra_opts+=("--cap-add=${opt##*=}") ;;
volume=*) extra_opts+=("--volume=${opt##*=}") ;;
*) log error "container_create: Invalid option: ${opt}" ;;
esac
done
@@ -47,6 +55,8 @@ container_start() {
log info "= Starting ${name} ="
podman start "${name}"
# Ensure /etc/shadow is readable
podman exec "${name}" bash -c "chmod u+r /etc/shadow"
echo
}
@@ -195,3 +205,15 @@ container_fetch() {
podman cp "${name}:${source}" "${destination}"
echo
}
container_tee() {
local name=${1}
local destination=${2}
tmpfile=$(mktemp /tmp/container-temp.XXXXXX)
log info "= Creating ${name}:${destination} from stdin ="
cat - > "${tmpfile}"
podman cp "${tmpfile}" "${name}:${destination}"
rm "${tmpfile}"
echo
}

9
infra/image/shdefaults Normal file
View File

@@ -0,0 +1,9 @@
#!/bin/bash -eu
# This file is meant to be source'd by other scripts
# Set default capabilities options for freeipa containers.
# Use +CAP to add the capability and -CAP to drop the capability.
CAP_DEFAULTS=(
"+DAC_READ_SEARCH" # Required for SSSD
"+SYS_PTRACE" # Required for debugging
)

View File

@@ -21,7 +21,7 @@
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
port: 52
#serial: 1234
# serial: 1234
refresh: 3600
retry: 900
expire: 1209600

View File

@@ -11,7 +11,7 @@
dest: "{{ ansible_facts['env'].HOME }}/password.txt"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0600
mode: "0600"
- name: Ensure symmetric vault exists with password from file.
ipavault:
ipaadmin_password: SomeADMINpassword

View File

@@ -16,7 +16,7 @@
dest: "{{ ansible_facts['env'].HOME }}/public.pem"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0600
mode: "0600"
- name: Ensure asymmetric vault exists with public key from file.
ipavault:
ipaadmin_password: SomeADMINpassword

View File

@@ -589,6 +589,20 @@ def ensure_fqdn(name, domain):
return name
def convert_to_sid(items):
"""Convert all items to SID, if possible."""
def get_sid(data):
try:
return get_trusted_domain_object_sid(data)
except ipalib_errors.NotFound:
return data
if items is None:
return None
if not isinstance(items, (list, tuple)):
items = [items]
return [get_sid(item) for item in items]
def api_get_realm():
return api.env.realm
@@ -903,6 +917,13 @@ def get_trusted_domain_sid_from_name(dom_name):
return unicode(sid) if sid is not None else None
def get_trusted_domain_object_sid(object_name):
"""Given an object name, returns de object SID."""
domain_validator = __get_domain_validator()
sid = domain_validator.get_trusted_domain_object_sid(object_name)
return unicode(sid) if sid is not None else None
class IPAParamMapping(Mapping):
"""
Provides IPA API mapping to playbook parameters or computed values.

View File

@@ -113,13 +113,14 @@ options:
externalmember:
description:
- List of members of a trusted domain in DOM\\name or name@domain form.
Requires "server" context.
required: false
type: list
elements: str
aliases: ["ipaexternalmember", "external_member"]
idoverrideuser:
description:
- User ID overrides to add
- User ID overrides to add. Requires "server" context.
required: false
type: list
elements: str
@@ -188,13 +189,14 @@ options:
externalmember:
description:
- List of members of a trusted domain in DOM\\name or name@domain form.
Requires "server" context.
required: false
type: list
elements: str
aliases: ["ipaexternalmember", "external_member"]
idoverrideuser:
description:
- User ID overrides to add
- User ID overrides to add. Requires "server" context.
required: false
type: list
elements: str
@@ -297,6 +299,7 @@ EXAMPLES = """
posix: yes
# Create an external group and add members from a trust to it.
# Module will fail if running under 'client' context.
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
@@ -327,7 +330,8 @@ RETURN = """
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
gen_add_list, gen_intersection_list, api_check_param
gen_add_list, gen_intersection_list, api_check_param, \
convert_to_sid
from ansible.module_utils import six
if six.PY3:
unicode = str
@@ -562,21 +566,29 @@ def main():
# The simple solution is to switch to client context for ensuring
# several groups simply if the user was not explicitly asking for
# the server context no matter if mixed types are used.
context = None
context = ansible_module.params_get("ipaapi_context")
if state == "present" and groups is not None and len(groups) > 1 \
and not FIX_6741_DEEPCOPY_OBJECTCLASSES:
_context = ansible_module.params_get("ipaapi_context")
if _context is None:
if context is None:
context = "client"
ansible_module.debug(
"Switching to client context due to an unfixed issue in "
"your IPA version: https://pagure.io/freeipa/issue/9349")
elif _context == "server":
elif context == "server":
ansible_module.fail_json(
msg="Ensuring several groups with server context is not "
"supported by your IPA version: "
"https://pagure.io/freeipa/issue/9349")
if (
(externalmember is not None
or idoverrideuser is not None)
and context == "client"
):
ansible_module.fail_json(
msg="Cannot use externalmember in client context."
)
# Use groups if names is None
if groups is not None:
names = groups
@@ -676,6 +688,23 @@ def main():
# Make sure group exists
res_find = find_group(ansible_module, name)
# external members must de handled as SID
externalmember = convert_to_sid(externalmember)
# idoverrides need to be compared through SID
idoverrideuser_sid = convert_to_sid(idoverrideuser)
res_idoverrideuser_sid = convert_to_sid(
(res_find or {}).get("member_idoverrideuser", []))
idoverride_set = dict(
list(zip(idoverrideuser_sid or [], idoverrideuser or [])) +
list(
zip(
res_idoverrideuser_sid or [],
(res_find or {}).get("member_idoverrideuser", [])
)
)
)
user_add, user_del = [], []
group_add, group_del = [], []
service_add, service_del = [], []
@@ -723,11 +752,12 @@ def main():
res_find = {}
# if we just created/modified the group, update res_find
res_find.setdefault("objectclass", [])
classes = list(res_find.setdefault("objectclass", []))
if external and not is_external_group(res_find):
res_find["objectclass"].append("ipaexternalgroup")
classes.append("ipaexternalgroup")
if posix and not is_posix_group(res_find):
res_find["objectclass"].append("posixgroup")
classes.append("posixgroup")
res_find["objectclass"] = classes
member_args = gen_member_args(
user, group, service, externalmember, idoverrideuser
@@ -752,11 +782,19 @@ def main():
)
)
# There are multiple ways to name an AD User, and any
# can be used in idoverrides, so we create the add/del
# lists based on SID, and then use the given user name
# to the idoverride.
(idoverrides_add,
idoverrides_del) = gen_add_del_lists(
idoverrideuser,
res_find.get("member_idoverrideuser")
)
idoverrideuser_sid, res_idoverrideuser_sid)
idoverrides_add = [
idoverride_set[sid] for sid in set(idoverrides_add)
]
idoverrides_del = [
idoverride_set[sid] for sid in set(idoverrides_del)
]
membermanager_user_add, membermanager_user_del = \
gen_add_del_lists(
@@ -790,7 +828,10 @@ def main():
)
)
idoverrides_add = gen_add_list(
idoverrideuser, res_find.get("member_idoverrideuser"))
idoverrideuser_sid, res_idoverrideuser_sid)
idoverrides_add = [
idoverride_set[sid] for sid in set(idoverrides_add)
]
membermanager_user_add = gen_add_list(
membermanager_user,
@@ -829,7 +870,10 @@ def main():
)
)
idoverrides_del = gen_intersection_list(
idoverrideuser, res_find.get("member_idoverrideuser"))
idoverrideuser_sid, res_idoverrideuser_sid)
idoverrides_del = [
idoverride_set[sid] for sid in set(idoverrides_del)
]
membermanager_user_del = gen_intersection_list(
membermanager_user, res_find.get("membermanager_user"))
@@ -872,7 +916,7 @@ def main():
if len(externalmember_del) > 0:
del_member_args["ipaexternalmember"] = \
externalmember_del
elif externalmember or external:
elif externalmember:
ansible_module.fail_json(
msg="Cannot add external members to a "
"non-external group."

View File

@@ -1,7 +1,7 @@
-r requirements-tests.txt
ipdb==0.13.4
pre-commit==2.20.0
flake8==7.0.0
flake8
flake8-bugbear
pylint>=3.2
wrapt==1.14.1

View File

@@ -34,7 +34,7 @@ Supported Distributions
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Fedora 40+
* Ubuntu 16.04 and 18.04

View File

@@ -25,7 +25,7 @@ Supported Distributions
* RHEL/CentOS 7.4+
* CentOS Stream 8+
* Fedora 26+
* Fedora 40+
* Ubuntu
* Debian

View File

@@ -279,6 +279,7 @@ def main():
options.no_sssd = False
options.sssd = not options.no_sssd
options.no_ac = False
options.dns_over_tls = False
nosssd_files = module.params.get('nosssd_files')
selinux_works = module.params.get('selinux_works')
krb_name = module.params.get('krb_name')
@@ -339,17 +340,19 @@ def main():
ca_subject)
ca_certs_trust = [(c, n,
certstore.key_policy_to_trust_flags(t, True, u))
for (c, n, t, u) in ca_certs]
for (c, n, t, u) in [x[0:4] for x in ca_certs]]
if hasattr(paths, "KDC_CA_BUNDLE_PEM"):
x509.write_certificate_list(
[c for c, n, t, u in ca_certs if t is not False],
[c for c, n, t, u in [x[0:4] for x in ca_certs]
if t is not False],
paths.KDC_CA_BUNDLE_PEM,
# mode=0o644
)
if hasattr(paths, "CA_BUNDLE_PEM"):
x509.write_certificate_list(
[c for c, n, t, u in ca_certs if t is not False],
[c for c, n, t, u in [x[0:4] for x in ca_certs]
if t is not False],
paths.CA_BUNDLE_PEM,
# mode=0o644
)
@@ -376,7 +379,12 @@ def main():
ssh_config_dir = paths.SSH_CONFIG_DIR
else:
ssh_config_dir = services.knownservices.sshd.get_config_dir()
update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp)
argspec_update_ssh_keys = getargspec(update_ssh_keys)
# Hotfix for https://github.com/freeipa/freeipa/pull/7343
if "options" in argspec_update_ssh_keys.args:
update_ssh_keys(hostname, ssh_config_dir, options, cli_server[0])
else:
update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp)
try:
os.remove(CCACHE_FILE)

View File

@@ -174,6 +174,7 @@ def main():
options.no_krb5_offline_passwords = module.params.get(
'no_krb5_offline_passwords')
options.krb5_offline_passwords = not options.no_krb5_offline_passwords
options.dns_over_tls = False
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
client_domain = hostname[hostname.find(".") + 1:]

View File

@@ -231,8 +231,6 @@ try:
cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
filename, client_domain, client_hostname, force=False,
configure_sssd=True):
# pylint: disable=global-variable-not-assigned
global options
options.force = force
options.sssd = configure_sssd
return ipa_client_install.configure_krb5_conf(

View File

@@ -152,7 +152,7 @@
ansible.builtin.copy:
src: "{{ ipaadmin_keytab }}"
dest: "{{ keytab_temp.path }}"
mode: 0600
mode: "0600"
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
when: ipaadmin_keytab is defined

View File

@@ -15,8 +15,3 @@
ipaclient_configure_dns_resolver:
state: absent
when: ipaclient_cleanup_dns_resolver | bool
#- name: Remove IPA client package
# ansible.builtin.package:
# name: "{{ ipaclient_packages }}"
# state: absent

View File

@@ -1,5 +0,0 @@
# defaults file for ipaclient
# vars/Fedora-25.yml
---
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'

View File

@@ -1,5 +0,0 @@
# defaults file for ipaclient
# vars/Fedora-26.yml
---
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'

View File

@@ -1,5 +0,0 @@
# defaults file for ipaclient
# vars/RedHat-7.3.yml
---
ipaclient_packages: [ "ipa-client", "ipa-admintools", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'

View File

@@ -2,4 +2,3 @@
# vars/RedHat-7
---
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'

View File

@@ -2,4 +2,3 @@
# vars/default.yml
---
ipaclient_packages: [ "ipa-client", "python3-libselinux" ]
#ansible_python_interpreter: '/usr/bin/python3'

View File

@@ -28,7 +28,7 @@ Supported Distributions
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Fedora 40+
* Ubuntu 16.04 and 18.04

View File

@@ -17,10 +17,10 @@ ipareplica_no_ui_redirect: no
ipaclient_mkhomedir: no
ipaclient_force_join: no
ipaclient_no_ntp: no
#ipaclient_ssh_trust_dns: no
#ipaclient_no_ssh: no
#ipaclient_no_sshd: no
#ipaclient_no_dns_sshfp: no
# ipaclient_ssh_trust_dns: no
# ipaclient_no_ssh: no
# ipaclient_no_sshd: no
# ipaclient_no_dns_sshfp: no
ipaclient_ssh_trust_dns: no
### certificate system ###
ipareplica_skip_schema_check: no

View File

@@ -80,6 +80,13 @@ except ImportError:
try:
from contextlib import contextmanager as contextlib_contextmanager
from ipapython.version import NUM_VERSION, VERSION
try:
from ipapython.version import parse_version
except ImportError:
# In IPA we either need pkg_resources or packaging Version
# class to compare versions with check_remote_version, so
# we let an exception to be raised if neither is available.
from pkg_resources import parse_version
if NUM_VERSION < 30201:
# See ipapython/version.py
@@ -99,8 +106,6 @@ try:
import dns.resolver as dnsresolver
import dns.reversename as dnsreversename
from pkg_resources import parse_version
from ipaclient.install.ipachangeconf import IPAChangeConf
from ipalib.install import certstore, sysrestore
from ipapython.ipautil import ipa_generate_password
@@ -331,6 +336,13 @@ options.add_agents = False
# ServerReplicaInstall
options.subject_base = None
options.ca_subject = None
# Hotfix for https://github.com/freeipa/freeipa/pull/7343
options.dns_over_tls = False
options.dns_over_tls_key = None
options.dns_over_tls_cert = None
options.dot_forwarders = None
options.dns_policy = None
# pylint: enable=attribute-defined-outside-init

View File

@@ -1,7 +0,0 @@
# defaults file for ipareplica
# vars/Fedora-25.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]

View File

@@ -1,7 +0,0 @@
# defaults file for ipareplica
# vars/Fedora-26.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]

View File

@@ -1,7 +0,0 @@
# defaults file for ipareplica
# vars/Fedora-27.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]

View File

@@ -25,7 +25,7 @@ Supported Distributions
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Fedora 40+
* Ubuntu 16.04 and 18.04

View File

@@ -16,10 +16,10 @@ ipaserver_random_serial_numbers: false
### client ###
ipaclient_mkhomedir: no
ipaclient_no_ntp: no
#ipaclient_ssh_trust_dns: no
#ipaclient_no_ssh: no
#ipaclient_no_sshd: no
#ipaclient_no_dns_sshfp: no
# ipaclient_ssh_trust_dns: no
# ipaclient_no_ssh: no
# ipaclient_no_sshd: no
# ipaclient_no_dns_sshfp: no
### certificate system ###
ipaserver_external_ca: no
### dns ###

View File

@@ -354,6 +354,13 @@ options.add_agents = False
# no_msdcs is deprecated
options.no_msdcs = False
# Hotfix for https://github.com/freeipa/freeipa/pull/7343
options.dns_over_tls = False
options.dns_over_tls_key = None
options.dns_over_tls_cert = None
options.dot_forwarders = None
options.dns_policy = None
# For pylint
options.external_cert_files = None
options.dirsrv_cert_files = None

View File

@@ -54,8 +54,3 @@
# 1 means that uninstall failed because IPA server was not configured
failed_when: uninstall.rc != 0 and uninstall.rc != 1
changed_when: uninstall.rc == 0
#- name: Remove IPA server packages
# ansible.builtin.package:
# name: "{{ ipaserver_packages }}"
# state: absent

View File

@@ -1,7 +0,0 @@
# defaults file for ipaserver
# vars/Fedora-25.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]

View File

@@ -1,7 +0,0 @@
# defaults file for ipaserver
# vars/Fedora-26.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]

View File

@@ -1,7 +0,0 @@
# defaults file for ipaserver
# vars/Fedora-27.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]

View File

@@ -25,7 +25,7 @@ Supported Distributions
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Fedora 40+
Requirements

View File

@@ -109,7 +109,7 @@
ansible.builtin.file:
path: /etc/sssd/pki
state: directory
mode: 0711
mode: "0711"
- name: Ensure /etc/sssd/pki/sssd_auth_ca_db.pem is absent
ansible.builtin.file:

View File

@@ -27,7 +27,7 @@ Supported Distributions
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Fedora 40+
Requirements

View File

@@ -201,7 +201,7 @@
ansible.builtin.file:
path: /etc/sssd/pki
state: directory
mode: 0711
mode: "0711"
- name: Ensure /etc/sssd/pki/sssd_auth_ca_db.pem is absent
ansible.builtin.file:

View File

@@ -48,7 +48,7 @@
ansible.builtin.file:
path: "/root/ca-less-test"
state: directory
mode: 0775
mode: "0775"
- name: Copy CA certificate
ansible.builtin.copy:

View File

@@ -48,7 +48,7 @@
ansible.builtin.file:
path: "/root/ca-less-test"
state: directory
mode: 0775
mode: "0775"
- name: Copy CA certificate
ansible.builtin.copy:

View File

@@ -47,7 +47,7 @@
ansible.builtin.copy:
dest: "/root/host.csr"
content: "{{ host_req.stdout }}"
mode: 0644
mode: "0644"
# TESTS

View File

@@ -45,7 +45,7 @@
ansible.builtin.copy:
dest: "/root/user.csr"
content: "{{ user_req.stdout }}"
mode: 0644
mode: "0644"
# TESTS

View File

@@ -7,6 +7,10 @@
# ipa_api_version: The installed FreeIPA API version.
#
---
- name: Ensure minimal facts are available
ansible.builtin.setup:
gather_subset: dns
- name: Retrieving FreeIPA version.
ansible.builtin.shell:
cmd: 'ipa --version | sed -n "s/VERSION: \([^,]*\).*API_VERSION: \([^,]*\).*/\1\\n\2/p"'
@@ -15,20 +19,31 @@
- name: Verify if host is an IPA server or client.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
RESULT=$(KRB5CCNAME={{ krb5ccname }} ipa server-show `hostname` && echo SERVER || echo CLIENT)
kdestroy -A -c {{ krb5ccname }}
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin >/dev/null
RESULT=$(KRB5CCNAME={{ krb5ccname }} ipa server-show `hostname` >/dev/null && echo SERVER || echo CLIENT)
kdestroy -A -c {{ krb5ccname }} >/dev/null
echo $RESULT
vars:
krb5ccname: "__check_ipa_host_is_client_or_server__"
register: output
register: check_client
- name: Verify if AD tests are possible
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin > /dev/null
RESULT=$(KRB5CCNAME={{ krb5ccname }} ipa server-find --all | grep "Enabled server roles")
kdestroy -A -c {{ krb5ccname }} > /dev/null
echo $RESULT
vars:
krb5ccname: "__check_ipa_host_is_client_or_server__"
register: check_ad_support
- name: Set FreeIPA facts.
ansible.builtin.set_fact:
ipa_version: "{{ ipa_cmd_version.stdout_lines[0] }}"
ipa_api_version: "{{ ipa_cmd_version.stdout_lines[1] }}"
ipa_host_is_client: "{{ (output.stdout_lines[-1] == 'CLIENT') | bool }}"
trust_test_is_supported: no
ipa_host_is_client: "{{ (check_client.stdout_lines[-1] == 'CLIENT') | bool }}"
trust_test_is_supported: "{{ 'AD trust agent' in check_ad_support.stdout }}"
- name: Ensure ipaserver_domain is set
when: ipaserver_domain is not defined
@@ -42,3 +57,8 @@
ansible.builtin.set_fact:
ipaserver_domain: "ipa.test"
when: "'fqdn' not in ansible_facts"
- name: Ensure ipaserver_realm is set
ansible.builtin.set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined

View File

@@ -28,7 +28,7 @@
become: true
vars:
ipaserver_external_cert_files_from_controller: "{{ groups.ipaserver[0] + '-chain.crt' }}"
#ipaserver_external_ca_file: "{{ groups.ipaserver[0] + '-cacert.asc' }}"
# ipaserver_external_ca_file: "{{ groups.ipaserver[0] + '-cacert.asc' }}"
roles:
- role: ipaserver

View File

@@ -34,7 +34,7 @@
become: true
vars:
ipaserver_external_cert_files: "/root/chain.crt"
#ipaserver_external_ca_file: "cacert.asc"
# ipaserver_external_ca_file: "cacert.asc"
pre_tasks:
- name: Copy "{{ groups.ipaserver[0] + '-chain.crt' }}" to /root/chain.crt on node

View File

@@ -1,8 +1,8 @@
---
- name: Test group
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
@@ -10,6 +10,9 @@
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# setup
@@ -51,6 +54,16 @@
register: result
failed_when: not result.changed or result.failed
- name: Ensure test service HTTP is present
ipaservice:
name: "{{ 'HTTP/' + fqdn_at_domain }}"
notify: Cleanup http service
- name: Ensure test service LDAP is present
ipaservice:
name: "{{ 'ldap/' + fqdn_at_domain }}"
notify: Cleanup ldap service
# TESTS
- name: Ensure group1 is present
@@ -298,11 +311,11 @@
register: result
failed_when: result.changed or result.failed
#- ipagroup:
# name: group1
# user:
# - user7
# action: member
# - ipagroup:
# name: group1
# user:
# - user7
# action: member
- name: Ensure user user7 is absent in group group1
ipagroup:
@@ -437,3 +450,16 @@
state: absent
register: result
failed_when: not result.changed or result.failed
# ansible-lint is complaining on the use of 'when' and requiring
# the use of handlers.
handlers:
- name: Cleanup http service
ipaservice:
name: "{{ 'HTTP/' + fqdn_at_domain }}"
state: absent
- name: Cleanup ldap service
ipaservice:
name: "{{ 'ldap/' + fqdn_at_domain }}"
state: absent

View File

@@ -0,0 +1,73 @@
---
- name: Test group AD external members idempotence
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server # external_member requires 'server' context
vars:
ad_user: "{{ test_ad_user | default('AD\\aduser') }}"
alt_user: "{{ test_alt_user | default('aduser@ad.ipa.test') }}"
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Ensure test group is absent.
ipagroup:
name: extgroup
state: absent
- name: Execute group tests if trust test environment is supported
when: trust_test_is_supported | default(false)
block:
- name: Ensure external group, with AD users, is present.
ipagroup:
name: extgroup
external: true
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure external group, with AD users, is present, again
ipagroup:
name: extgroup
external: true
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure external group, with alternate name AD users, is present
ipagroup:
name: extgroup
external: true
external_member: "{{ alt_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure external_member is absent
ipagroup:
name: extgroup
external_member: "{{ ad_user }}"
action: member
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure external_member is absent, again
ipagroup:
name: extgroup
external_member: "{{ alt_user }}"
action: member
state: absent
register: result
failed_when: result.failed or result.changed
always:
- name: Cleanup environment.
ipagroup:
name: extgroup
state: absent

View File

@@ -4,6 +4,9 @@
become: no
gather_facts: no
vars:
ad_user: "{{ test_ad_user | default('AD\\aduser') }}"
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
@@ -18,6 +21,16 @@
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
- name: Ensuref fail if externalmember is used in client context.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
name: ThisShouldNotWork
external_member: "{{ ad_user }}"
external: true
register: result
failed_when: not (result.failed and result.msg == "Cannot use externalmember in client context.")
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.

View File

@@ -1,12 +1,16 @@
---
- name: Find trust
hosts: ipaserver
- name: Test groups with external members
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipaapi_context: server # external_member requires 'server' context
vars:
ad_user: "{{ test_ad_user | default('AD\\aduser') }}"
alt_user: "{{ test_alt_user | default('aduser@ad.ipa.test') }}"
tasks:
@@ -24,86 +28,121 @@
when: trust_test_is_supported | default(false)
block:
- name: Add nonposix group.
- name: Ensure nonposix group is present
ipagroup:
name: extgroup
nonposix: true
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external
- name: Ensure nonposix group is present, again
ipagroup:
name: extgroup
nonposix: true
register: result
failed_when: result.failed or result.changed
- name: Ensure nonposix group is external
ipagroup:
name: extgroup
external: true
register: result
failed_when: result.failed or not result.changed
- name: Add AD users to group
- name: Ensure nonposix group has AD users
ipagroup:
name: extgroup
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Add AD users to group, again
- name: Ensure nonposix group has AD users, again
ipagroup:
name: extgroup
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
- name: Remove external group
- name: Ensure nonposix group is absent.
ipagroup:
name: extgroup
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix, external group, with AD users.
- name: Ensure nonposix group is absent, again.
ipagroup:
name: extgroup
nonposix: true
external: true
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix, external group, with AD users, again.
ipagroup:
name: extgroup
nonposix: true
external: true
external_member: "AD\\Domain Users"
state: absent
register: result
failed_when: result.failed or result.changed
- name: Remove group
- name: Ensure external group is present, with AD users.
ipagroup:
name: extgroup
external: true
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure external group is present, with AD alternate users.
ipagroup:
name: extgroup
external: true
external_member: "{{ alt_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure external group is present, with AD users, again.
ipagroup:
name: extgroup
external: true
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure external group is absent
ipagroup:
name: extgroup
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix group.
- name: Ensure external group is absent, again
ipagroup:
name: extgroup
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure nonposix group is present.
ipagroup:
name: extgroup
nonposix: true
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, and add users.
- name: Ensure group is external, and has AD users.
ipagroup:
name: extgroup
external: true
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, and add users, again.
- name: Ensure group is external, and has AD alternate users.
ipagroup:
name: extgroup
external: true
external_member: "AD\\Domain Users"
external_member: "{{ alt_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure group is external, and has AD users, again.
ipagroup:
name: extgroup
external: true
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
@@ -117,7 +156,7 @@
- name: Ensure external group members are present
ipagroup:
name: extgroup_members
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
action: member
register: result
failed_when: result.failed or not result.changed
@@ -125,7 +164,7 @@
- name: Ensure external group members are present, again
ipagroup:
name: extgroup_members
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
action: member
register: result
failed_when: result.failed or result.changed
@@ -133,16 +172,25 @@
- name: Ensure external group members are absent
ipagroup:
name: extgroup_members
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
action: member
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure external group alternate members are absent
ipagroup:
name: extgroup_members
external_member: "{{ alt_user }}"
action: member
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure external group members are absent, again
ipagroup:
name: extgroup_members
external_member: "AD\\Domain Users"
external_member: "{{ ad_user }}"
action: member
state: absent
register: result

View File

@@ -1,12 +1,17 @@
---
- name: Test group
- name: Test group idoverrideuser
hosts: ipaserver
become: yes
gather_facts: yes
become: false
gather_facts: false
module_defaults:
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
vars:
ad_user: "{{ test_ad_user | default('AD\\aduser') }}"
ad_domain: "{{ test_ad_domain | default('ad.ipa.test') }}"
ad_user: "{{ test_ad_user | default('AD\\aduser') }}"
alt_user: "{{ test_alt_user | default('aduser@ad.ipa.test') }}"
tasks:
- name: Include tasks ../env_freeipa_facts.yml
@@ -15,38 +20,42 @@
- name: Execute tests if ipa_verison >= 4.8.7 and trust test environment is supported
when: ipa_version is version("4.8.7", ">=") and trust_test_is_supported | default(false)
block:
- name: Create idoverrideuser.
ansible.builtin.shell: |
kinit -c idoverride_cache admin <<< SomeADMINpassword
ipa idoverrideuser-add "Default Trust View" {{ ad_user }}
kdestroy -A -q -c idoverride_cache
- name: Ensure test idoverrideuser is present
ipaidoverrideuser:
idview: "Default Trust View"
anchor: "{{ ad_user }}"
register: result
failed_when: result.failed and "no modifications to be performed" not in result.msg
- name: Remove testing groups.
- name: Ensure test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- idovergroup
- idovergroup
state: absent
- name: Add group with idoverrideuser.
- name: Ensure group with idoverrideuser is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Add group with idoverrideuser, again.
- name: Ensure group with idoverrideuser is present, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
- name: Remove idoverrideuser member.
- name: Ensure group with alternative idoverrideuser is present.
ipagroup:
name: idovergroup
idoverrideuser: "{{ alt_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure idoverrideuser member is absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
action: member
@@ -54,9 +63,8 @@
register: result
failed_when: result.failed or not result.changed
- name: Remove idoverrideuser member, again.
- name: Ensure idoverrideuser member is absent, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
action: member
@@ -64,7 +72,7 @@
register: result
failed_when: result.failed or result.changed
- name: Add idoverrideuser member.
- name: Ensure idoverrideuser member is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
@@ -73,7 +81,7 @@
register: result
failed_when: result.failed or not result.changed
- name: Add idoverrideuser member, again.
- name: Ensure idoverrideuser member is present, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
@@ -82,24 +90,17 @@
register: result
failed_when: result.failed or result.changed
- name: Cleanup idoverrideuser member.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
state: absent
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- idovergroup
state: absent
always:
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- idovergroup
state: absent
- name: Remove idoverrideuser.
ansible.builtin.shell:
cmd: |
kinit -c idoverride_cache admin <<< SomeADMINpassword
ipa idoverrideuser-del "Default Trust View" {{ ad_user }}
kdestroy -A -q -c idoverride_cache
ipaidoverrideuser:
idview: "Default Trust View"
anchor: "{{ ad_user }}"
continue: true
state: absent

View File

@@ -191,35 +191,35 @@
# disabled can only be checked with enabled hosts, all hosts above are
# not enabled.
#- name: Hosts host1..host6 disabled
# ipahost:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name:
# - "{{ host1_fqdn }}"
# - "{{ host2_fqdn }}"
# - "{{ host3_fqdn }}"
# - "{{ host4_fqdn }}"
# - "{{ host5_fqdn }}"
# - "{{ host6_fqdn }}"
# state: disabled
# register: result
# failed_when: not result.changed or result.failed
# - name: Hosts host1..host6 disabled
# ipahost:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name:
# - "{{ host1_fqdn }}"
# - "{{ host2_fqdn }}"
# - "{{ host3_fqdn }}"
# - "{{ host4_fqdn }}"
# - "{{ host5_fqdn }}"
# - "{{ host6_fqdn }}"
# state: disabled
# register: result
# failed_when: not result.changed or result.failed
#
#- name: Hosts host1..host6 disabled again
# ipahost:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name:
# - "{{ host1_fqdn }}"
# - "{{ host2_fqdn }}"
# - "{{ host3_fqdn }}"
# - "{{ host4_fqdn }}"
# - "{{ host5_fqdn }}"
# - "{{ host6_fqdn }}"
# state: disabled
# register: result
# failed_when: result.changed or result.failed
# - name: Hosts host1..host6 disabled again
# ipahost:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name:
# - "{{ host1_fqdn }}"
# - "{{ host2_fqdn }}"
# - "{{ host3_fqdn }}"
# - "{{ host4_fqdn }}"
# - "{{ host5_fqdn }}"
# - "{{ host6_fqdn }}"
# state: disabled
# register: result
# failed_when: result.changed or result.failed
- name: Hosts host1..host6 absent
ipahost:

View File

@@ -16,7 +16,8 @@
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
idview: ThisShouldNotWork
anchor: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client

View File

@@ -56,7 +56,7 @@
first: pinky
last: Acme
initials: pa
#password: foo2
# password: foo2
principal: pa
random: yes
street: PinkyStreet
@@ -73,8 +73,8 @@
# sshpubkey
userauthtype: password,radius,otp
userclass: PinkyUserClass
#radius: "http://some.link/"
#radiususer: PinkyRadiusUser
# radius: "http://some.link/"
# radiususer: PinkyRadiusUser
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
@@ -82,8 +82,8 @@
# certificate
noprivate: yes
nomembers: false
#issuer: PinkyIssuer
#subject: PinkySubject
# issuer: PinkyIssuer
# subject: PinkySubject
register: result
failed_when: not result.changed or result.failed

View File

@@ -190,7 +190,7 @@
first: pinky
last: Acme
initials: pa
#password: foo2
# password: foo2
principal: pa
random: yes
street: PinkyStreet
@@ -207,8 +207,8 @@
# sshpubkey
userauthtype: password,radius,otp
userclass: PinkyUserClass
#radius: "http://some.link/"
#radiususer: PinkyRadiusUser
# radius: "http://some.link/"
# radiususer: PinkyRadiusUser
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
@@ -216,8 +216,8 @@
# certificate
noprivate: yes
nomembers: false
#issuer: PinkyIssuer
#subject: PinkySubject
# issuer: PinkyIssuer
# subject: PinkySubject
register: result
failed_when: not result.changed or result.failed
@@ -234,7 +234,7 @@
first: pinky
last: Acme
initials: pa
#password: foo2
# password: foo2
principal: pa
random: yes
street: PinkyStreet
@@ -251,8 +251,8 @@
# sshpubkey
userauthtype: password,radius,otp
userclass: PinkyUserClass
#radius: "http://some.link/"
#radiususer: PinkyRadiusUser
# radius: "http://some.link/"
# radiususer: PinkyRadiusUser
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
@@ -260,8 +260,8 @@
# certificate
noprivate: yes
nomembers: false
#issuer: PinkyIssuer
#subject: PinkySubject
# issuer: PinkyIssuer
# subject: PinkySubject
register: result
failed_when: result.changed or result.failed

View File

@@ -20,7 +20,7 @@
ansible.builtin.copy:
src: "{{ playbook_dir }}/{{ item }}"
dest: "{{ ansible_facts['env'].HOME }}/{{ item }}"
mode: 0644
mode: "0644"
with_items:
- A_private.pem
- A_public.pem

View File

@@ -79,6 +79,20 @@ shift
prepare_container "${scenario}" "${IMAGE_TAG}"
start_container "${scenario}"
log info "Wait till systemd-journald is running"
max=20
wait=2
count=0
while ! podman exec "${scenario}" ps -x | grep -q "systemd-journald"
do
if [ $count -ge $max ]; then
die "Timeout: systemd-journald is not starting up"
fi
count=$((count+1))
log none "Waiting ${wait} seconds .."
sleep ${wait}
done
# wait for FreeIPA services to be available (usually ~45 seconds)
log info "Wait for container to be initialized."
wait=15