Compare commits

...

36 Commits

Author SHA1 Message Date
Rafael Guterres Jeffman
22700620c6 ipaconfig: Validate emaildomain
When setting the default email domain, there was no validation on the
provide value. Using ipapython.validate.Email applies the same
validation method as implemented in IPA.

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2025-03-05 16:49:11 -03: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
Rafael Guterres Jeffman
9195494f37 Merge pull request #1243 from t-woerner/ipareplica_ip_addresses_use_for_client
ipareplica: Pass ipareplica_ip_addresses to client deployment part
2024-12-12 10:00:09 -03:00
Thomas Woerner
81abf6889b ipareplica: Pass ipareplica_ip_addresses to client deployment part
The IP addresses set with ipareplica_ip_addresses have not been passed
to ipaclient role for client deployment part. This resulted in not
setting the IP addresses.

The description for ipareplica_ip_addresses in the ipareplica README and
also the role modules was wrong and have been fixed to "List of IPA
replica IP addresses".

Related: https://pagure.io/freeipa/issue/7405

Resolves: https://github.com/freeipa/ansible-freeipa/issues/1244
2024-12-12 12:10:56 +01:00
Thomas Woerner
81906edec6 Merge pull request #1322 from rjeffman/rhel70023
ipagroup: Correctly handle externalmember in member actions
2024-12-12 12:02:37 +01:00
Thomas Woerner
5071653db3 Merge pull request #1321 from rjeffman/rhel-68439
ipasudorule: Evaluate all members related to hosts and users
2024-12-12 11:27:01 +01:00
Rafael Guterres Jeffman
df4ec30a51 ipasudorule: Evaluate all members related to hosts and users
When handling users and hosts is ipasudorule we were missing nome entry
attributes returned from FreeIPA, which would cause the add/del lists to
be incorrectly generated.

By adding the proper lists, both attributes are handled correctly.

A new test to verify the fix is added:

    tests/sudorule/test_sudorule_user_host_external.yml

Fixes https://issues.redhat.com/browse/RHEL-68439
2024-12-11 10:56:11 -03:00
Thomas Woerner
73160a037b Merge pull request #1323 from rjeffman/rhel70021
ipacert: Revoking with  removeFromCRL should be handled as cert release
2024-12-11 14:54:59 +01:00
Rafael Guterres Jeffman
b7ed9ecfd5 Merge pull request #1324 from t-woerner/no_role_plugin_duplicates
utils/build-galaxy-release.sh: Do not create duplicates for role plugins
2024-12-11 10:29:07 -03:00
Thomas Woerner
a4f608854d ansible_ipa_server.py: Calm down ansible-test "metaclass-boilerplate"
ansible-test sanity test "metaclass-boilerplate" fails now to recognize
the line "__metaclass__ = type" if there is a pylint disable comment
appended to the same line to not fail on using bad class naming.

The pylint disable comment has been moved to an extra preceding line and
an additional enable commend has been added after the metaclass line.
2024-12-11 14:19:09 +01:00
Thomas Woerner
8e6c5e566d utils/build-galaxy-release.sh: Do not create duplicates for role plugins
This change reduces the size of the Ansible collection and removes unused
files.

While creating the collection, the role plugins have been linked into the
global plugin folders, but a subsequent sed call replaced the links with
changed files. The original files have also been changed with another sed
call in the same way. This resulted in the duplication of the changed
files.

The plugins of the roles are now moved into the global plugin folders and
only changed there. The now empty plugin folders in the roles are
removed.
2024-12-10 17:12:09 +01:00
Rafael Guterres Jeffman
431dc8667a ipagroup: Correctly handle externalmember in member actions
When creating the lists of external members, the attribute
'ipaexternalmember' also needs to be added to the list of external
members that are part of the group object for external groups.

A test to verify the correct behavior was added and the test suite for
group external members have been cleaned up with 'yes' values changed to
'true' and the use of module_defaults.
2024-12-10 08:25:49 -03:00
Rafael Guterres Jeffman
bc16ccaef7 ipacert: Revoking with removeFromCRL should be handled as cert release
When a revoked certificate with reason 6 (certificateHold) is revoked
with reason 8 (removeFromCRL), the effect is that the certificate is
valid again, as it is the same procedure as 'state: release'.

This is, at least, the behavior with IPA CLI comands, which is
implemented by this patch.

A new test is added to verify this behavior:

    tests/cert/test_cert_remove_hold_with_removeFromCRL.yml
2024-12-05 15:42:58 -03:00
Thomas Woerner
227c95e62e Merge pull request #1319 from rjeffman/fix_show_broad_exception
modules: Do not hide errors using IPA *_show command with Exception
2024-12-03 15:09:14 +01:00
Rafael Guterres Jeffman
5abb515c92 utils/templates: Use ipalib_errors.NotFound instead of Exception
Modify the plugin templates so that the code generated does not hide
errors when querying IPA wih *_show command by handlig only the exeption
where an object is not found.
2024-12-02 23:27:56 -03:00
Rafael Guterres Jeffman
1c4b50fa51 modules: Do not hide errors using IPA *_show command with Exception
When searching for objects with *_show IPA API command, most plugins
were hiding errors other than "ipalib_errors.NotFound" by handling the
broad exception Exception instead.

This patch uses "ipalib_errors.NotFound" whenever "*_show" is used so
that the only exception handled is when an object is not found. Other
errors will not be handled making the module break as expected.
2024-12-02 22:58:51 -03:00
Rafael Guterres Jeffman
8fc2de1673 Merge pull request #1318 from t-woerner/testing_container_create_enable_cap_sys_admin
infra/image: Use SYS_ADMIN capability for server deployment
2024-12-02 14:41:35 -03:00
Thomas Woerner
8d74fe34ef Enable c10s testing for PRs and nightly and after merge testing 2024-12-02 15:38:39 +01:00
Thomas Woerner
87ad46f7a4 Enable to build c10s test container image 2024-12-02 15:11:48 +01:00
Thomas Woerner
4c3f4e6f7d infra/image: Use SYS_ADMIN capability for server deployment
This adds the capabilities SYS_ADMIN and SYSLOG to the container_create
call in build.sh as long as server deployment has been enabled.

The privileged option has been removed as it is no longer needed.

The hostnamectl-wrapper for the container has been removed as it is no
longer needed.
2024-12-02 15:06:44 +01:00
Rafael Guterres Jeffman
489f4d5784 Merge pull request #1316 from t-woerner/c10s_niddomainname
infra/image/dockerfile/c10s: Fix client part deployment for the server
2024-11-29 08:39:21 -03:00
Rafael Guterres Jeffman
29fc03c625 Merge pull request #1315 from t-woerner/container_copy_fetch
infra/image/shcontainer: New container_copy and container_fetch
2024-11-28 11:02:44 -03:00
Thomas Woerner
2dc1deeb87 infra/image/dockerfile/c10s: Fix client part deployment for the server
The client part deployment fails in the configuration of NIS. The command
/usr/bin/nisdomainname is failing in a container in this task as the
container is not privileged.

The hostnamectl-wrapper is copied from the freeipa-container container
project to replace /usr/bin/nisdomainname in the container.
2024-11-19 15:54:03 +01:00
Thomas Woerner
82a53b9ae4 infra/image/shcontainer: New container_copy and container_fetch
container_copy can be used to copy a file to the container,
container_fetch can be used to copy a file from the container.

For more information, please have a look at the podman-cp man page.
2024-11-19 15:08:46 +01:00
90 changed files with 862 additions and 377 deletions

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

@@ -9,7 +9,7 @@ variables:
ansible_version: "-core >=2.16,<2.17"
ansible_latest: "-core"
ansible_minimum: "-core <2.16"
distros: "fedora-latest,c9s,fedora-rawhide"
distros: "fedora-latest,c9s,c10s,fedora-rawhide"
stages:

View File

@@ -12,7 +12,7 @@ trigger: none
pool:
vmImage: 'ubuntu-24.04'
variables: { distros: "fedora-latest,fedora-rawhide,c9s" }
variables: { distros: "fedora-latest,fedora-rawhide,c9s,c10s" }
stages:

View File

@@ -14,8 +14,8 @@ pool:
variables:
# We need to have two sets, as c8s is not supported by all ansible versions
recent_distros: "fedora-latest,fedora-rawhide,c9s"
distros: "fedora-latest,fedora-rawhide,c9s,c8s"
recent_distros: "fedora-latest,fedora-rawhide,c10s,c9s"
distros: "fedora-latest,fedora-rawhide,c10s,c9s,c8s"
ansible_latest: "-core"
ansible_minimum: "-core <2.16"
ansible_version: "-core >=2.16,<2.17"

View File

@@ -6,7 +6,7 @@ pool:
vmImage: 'ubuntu-20.04'
variables:
distros: "fedora-latest,c9s,c8s,fedora-rawhide"
distros: "fedora-latest,c10s,c9s,c8s,fedora-rawhide"
ansible_version: "-core >=2.15,<2.16"
stages:

View File

@@ -23,7 +23,7 @@ jobs:
- script: ansible-galaxy collection install containers.podman
displayName: Install Ansible Galaxy collections
- script: infra/image/build.sh -p -s ${{ parameters.distro }}
- script: infra/image/build.sh -s ${{ parameters.distro }}
displayName: Build ${{ parameters.distro }} base image
env:
ANSIBLE_ROLES_PATH: "${PWD}/roles"

View File

@@ -0,0 +1,21 @@
#
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# Example:
#
# ipa_disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
# If no variables are set, set "empty: true" as at least
# one item is needed in the set.
---
variables:
empty: true
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
# ipa_disabled_modules: >-
# ipa_disabled_tests: >-

View File

@@ -15,7 +15,7 @@ valid_distro() {
usage() {
local prog="${0##*/}"
cat << EOF
usage: ${prog} [-h] [-p] [-n HOSTNAME] [-s] distro
usage: ${prog} [-h] [-n HOSTNAME] [-s] distro
${prog} build a container image to test ansible-freeipa.
EOF
}
@@ -41,14 +41,14 @@ cpus="2"
memory="3g"
quayname="quay.io/ansible-freeipa/upstream-tests"
deploy_server="N"
privileged=""
deploy_capabilities="SYS_ADMIN,SYSLOG"
capabilities=""
while getopts ":hn:ps" option
while getopts ":hn:s" option
do
case "${option}" in
h) help && exit 0 ;;
n) hostname="${OPTARG}" ;;
p) privileged="privileged" ;;
s) deploy_server="Y" ;;
*) die -u "Invalid option: ${option}" ;;
esac
@@ -66,6 +66,8 @@ container_check
if [ "${deploy_server}" == "Y" ]
then
capabilities="${deploy_capabilities}"
[ -n "$(command -v "ansible-playbook")" ] || die "ansible-playbook is required to install FreeIPA."
deploy_playbook="${TOPDIR}/playbooks/install-server.yml"
@@ -89,7 +91,7 @@ container_create "${name}" "${tag}" \
"hostname=${hostname}" \
"memory=${memory}" \
"cpus=${cpus}" \
"${privileged}"
"${capabilities:+capabilities=$capabilities}"
container_commit "${name}" "${quayname}:${tag}"
if [ "${deploy_server}" == "Y" ]

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; \
@@ -9,7 +9,8 @@ dnf --assumeyes install \
bash \
systemd \
procps-ng \
iproute; \
iproute \
hostname; \
rm -rf /var/cache/dnf/;
RUN (cd /lib/systemd/system/; \

View File

@@ -18,7 +18,7 @@ container_create() {
hostname=*) extra_opts+=("--${opt}") ;;
cpus=*) extra_opts+=("--${opt}") ;;
memory=*) extra_opts+=("--${opt}") ;;
privileged) extra_opts+=("--${opt}") ;;
capabilities=*) extra_opts+=("--cap-add=${opt##*=}") ;;
*) log error "container_create: Invalid option: ${opt}" ;;
esac
done
@@ -175,3 +175,23 @@ container_image_list() {
container_check() {
[ -n "$(command -v "podman")" ] || die "podman is required."
}
container_copy() {
local name="${1}"
local source="${2}"
local destination="${3}"
log info "= Copying ${source} to ${name}:${destination} ="
podman cp "${source}" "${name}:${destination}"
echo
}
container_fetch() {
local name="${1}"
local source="${2}"
local destination="${3}"
log info "= Copying ${name}:${source} to ${destination} ="
podman cp "${name}:${source}" "${destination}"
echo
}

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

@@ -33,7 +33,7 @@ __all__ = ["DEBUG_COMMAND_ALL", "DEBUG_COMMAND_LIST",
"paths", "tasks", "get_credentials_if_valid", "Encoding",
"DNSName", "getargspec", "certificate_loader",
"write_certificate_list", "boolean", "template_str",
"urlparse", "normalize_sshpubkey"]
"urlparse", "normalize_sshpubkey", "Email"]
DEBUG_COMMAND_ALL = 0b1111
# Print the while command list:
@@ -116,6 +116,7 @@ try:
from ipalib.krb_utils import get_credentials_if_valid
from ipapython.dnsutil import DNSName
from ipapython import kerberos
from ipapython.ipavalidate import Email
try:
from ipalib.x509 import Encoding
@@ -589,6 +590,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 +918,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

@@ -106,7 +106,7 @@ RETURN = '''
'''
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, compare_args_ipa
IPAAnsibleModule, compare_args_ipa, ipalib_errors
)
@@ -124,7 +124,7 @@ class AutomountMap(IPAAnsibleModule):
location,
{"automountmapname": name, "all": True}
)
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
return None
return response["result"]
@@ -132,7 +132,7 @@ class AutomountMap(IPAAnsibleModule):
"""Check if 'name' is an indirect map for 'parentmap'."""
try:
maps = self.ipa_command("automountmap_find", location, {})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
return []
result = []

View File

@@ -487,6 +487,8 @@ def main():
# revoked
reason = ansible_module.params_get("revocation_reason")
if reason is not None:
reason = get_revocation_reason(ansible_module, reason)
# general
serial_number = ansible_module.params.get("serial_number")
@@ -521,6 +523,9 @@ def main():
invalid.append("revocation_reason")
if state == "revoked":
invalid.extend(["certificate_out", "chain"])
# Reason 8 (revomeFromCRL) is the same as release hold
if reason == 8:
state = "released"
elif state == "held":
reason = 6 # certificateHold

View File

@@ -344,7 +344,7 @@ config:
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, ipalib_errors
IPAAnsibleModule, compare_args_ipa, ipalib_errors, Email
def config_show(module):
@@ -356,7 +356,7 @@ def config_show(module):
def get_netbios_name(module):
try:
_result = module.ipa_command_no_name("trustconfig_show", {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
return None
return _result["result"]["ipantflatname"][0]
@@ -515,6 +515,13 @@ def main():
msg="Argument '%s' must be between %d and %d."
% (arg, minimum, maximum))
# verify email domain
emaildomain = params.get("ipadefaultemaildomain", None)
if emaildomain:
if not Email("test@{0}".format(emaildomain)):
ansible_module.fail_json(
msg="Invalid 'emaildomain' value: %s" % emaildomain)
changed = False
exit_args = {}

View File

@@ -124,14 +124,14 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
IPAAnsibleModule, compare_args_ipa, ipalib_errors
def find_delegation(module, name):
"""Find if a delegation with the given name already exist."""
try:
_result = module.ipa_command("delegation_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if delegation name is not found.
return None
return _result["result"]

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
@@ -746,13 +776,25 @@ def main():
(externalmember_add,
externalmember_del) = gen_add_del_lists(
externalmember, res_find.get("member_external"))
externalmember, (
list(res_find.get("member_external", []))
+ list(res_find.get("ipaexternalmember", []))
)
)
# 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(
@@ -780,9 +822,16 @@ def main():
service_add = gen_add_list(
service, res_find.get("member_service"))
externalmember_add = gen_add_list(
externalmember, res_find.get("member_external"))
externalmember, (
list(res_find.get("member_external", []))
+ list(res_find.get("ipaexternalmember", []))
)
)
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,
@@ -815,9 +864,16 @@ def main():
service_del = gen_intersection_list(
service, res_find.get("member_service"))
externalmember_del = gen_intersection_list(
externalmember, res_find.get("member_external"))
externalmember, (
list(res_find.get("member_external", []))
+ list(res_find.get("ipaexternalmember", []))
)
)
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"))
@@ -860,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

@@ -155,7 +155,7 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
IPAAnsibleModule, compare_args_ipa, ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -168,7 +168,7 @@ def find_idoverridegroup(module, idview, anchor):
_result = module.ipa_command("idoverridegroup_show", idview,
{"ipaanchoruuid": anchor,
"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if idoverridegroup anchor is not found.
return None
return _result["result"]

View File

@@ -315,7 +315,8 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, encode_certificate, convert_input_certificates
gen_intersection_list, encode_certificate, convert_input_certificates, \
ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -328,7 +329,7 @@ def find_idoverrideuser(module, idview, anchor):
_result = module.ipa_command("idoverrideuser_show", idview,
{"ipaanchoruuid": anchor,
"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if idoverrideuser anchor is not found.
return None

View File

@@ -184,7 +184,8 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, template_str, urlparse
IPAAnsibleModule, compare_args_ipa, template_str, urlparse, \
ipalib_errors
from ansible.module_utils import six
from copy import deepcopy
import string
@@ -269,7 +270,7 @@ def find_idp(module, name):
"""Find if a idp with the given name already exist."""
try:
_result = module.ipa_command("idp_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if idp name is not found.
return None

View File

@@ -143,7 +143,8 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name
IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name, \
ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -154,7 +155,7 @@ def find_idrange(module, name):
"""Find if a idrange with the given name already exist."""
try:
_result = module.ipa_command("idrange_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if idrange name is not found.
return None
return _result["result"]

View File

@@ -138,7 +138,7 @@ def find_idview(module, name):
"""Find if a idview with the given name already exist."""
try:
_result = module.ipa_command("idview_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if idview name is not found.
return None
return _result["result"]

View File

@@ -76,14 +76,14 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
IPAAnsibleModule, compare_args_ipa, ipalib_errors
def find_location(module, name):
"""Find if a location with the given name already exist."""
try:
_result = module.ipa_command("location_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if location name is not found.
return None
return _result["result"]

View File

@@ -154,14 +154,14 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, to_text
IPAAnsibleModule, compare_args_ipa, to_text, ipalib_errors
def find_permission(module, name):
"""Find if a permission with the given name already exist."""
try:
_result = module.ipa_command("permission_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if permission name is not found.
return None
_res = _result["result"]

View File

@@ -124,7 +124,7 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list
gen_intersection_list, ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -135,7 +135,7 @@ def find_privilege(module, name):
"""Find if a privilege with the given name already exist."""
try:
_result = module.ipa_command("privilege_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if privilege name is not found.
return None
return _result["result"]

View File

@@ -129,7 +129,7 @@ EXAMPLES = """
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, gen_add_del_lists, compare_args_ipa, \
gen_intersection_list, ensure_fqdn
gen_intersection_list, ensure_fqdn, ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -140,7 +140,7 @@ def find_role(module, name):
"""Find if a role with the given name already exist."""
try:
_result = module.ipa_command("role_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if role name is not found.
return None
return _result["result"]

View File

@@ -113,14 +113,14 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
IPAAnsibleModule, compare_args_ipa, ipalib_errors
def find_selfservice(module, name):
"""Find if a selfservice with the given name already exist."""
try:
_result = module.ipa_command("selfservice_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if selfservice name is not found.
return None
return _result["result"]

View File

@@ -192,14 +192,14 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, DNSName
IPAAnsibleModule, compare_args_ipa, DNSName, ipalib_errors
def find_server(module, name):
"""Find if a server with the given name already exist."""
try:
_result = module.ipa_command("server_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if server name is not found.
return None
return _result["result"]
@@ -214,7 +214,7 @@ def server_role_status(module, name):
"include_master": True,
"raw": True,
"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if server name is not found.
return None
return _result["result"][0]

View File

@@ -142,7 +142,7 @@ def find_servicedelegationrule(module, name):
try:
_result = module.ipa_command("servicedelegationrule_show", name,
{"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if servicedelegationrule name is not found.
return None
return _result["result"]

View File

@@ -106,7 +106,7 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, gen_add_del_lists, gen_add_list, gen_intersection_list, \
servicedelegation_normalize_principals
servicedelegation_normalize_principals, ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -118,7 +118,7 @@ def find_servicedelegationtarget(module, name):
try:
_result = module.ipa_command("servicedelegationtarget_show", name,
{"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if servicedelegationtarget name is not found.
return None
return _result["result"]

View File

@@ -710,7 +710,11 @@ def main():
# Generate addition and removal lists
host_add, host_del = gen_add_del_lists(
entry.host, res_find.get('memberhost_host', []))
entry.host, (
list(res_find.get('memberhost_host', []))
+ list(res_find.get('externalhost', []))
)
)
hostgroup_add, hostgroup_del = gen_add_del_lists(
entry.hostgroup,
@@ -721,7 +725,11 @@ def main():
entry.hostmask, res_find.get('hostmask', []))
user_add, user_del = gen_add_del_lists(
entry.user, res_find.get('memberuser_user', []))
entry.user, (
list(res_find.get('memberuser_user', []))
+ list(res_find.get('externaluser', []))
)
)
group_add, group_del = gen_add_del_lists(
entry.group, res_find.get('memberuser_group', []))
@@ -751,8 +759,7 @@ def main():
# the provided list against both users and external
# users list.
runasuser_add, runasuser_del = gen_add_del_lists(
entry.runasuser,
(
entry.runasuser, (
list(res_find.get('ipasudorunas_user', []))
+ list(res_find.get('ipasudorunasextuser', []))
)
@@ -785,7 +792,11 @@ def main():
# the sudorule already
if entry.host is not None:
host_add = gen_add_list(
entry.host, res_find.get("memberhost_host"))
entry.host, (
list(res_find.get("memberhost_host", []))
+ list(res_find.get("externalhost", []))
)
)
if entry.hostgroup is not None:
hostgroup_add = gen_add_list(
entry.hostgroup,
@@ -796,7 +807,11 @@ def main():
entry.hostmask, res_find.get("hostmask"))
if entry.user is not None:
user_add = gen_add_list(
entry.user, res_find.get("memberuser_user"))
entry.user, (
list(res_find.get('memberuser_user', []))
+ list(res_find.get('externaluser', []))
)
)
if entry.group is not None:
group_add = gen_add_list(
entry.group, res_find.get("memberuser_group"))
@@ -862,7 +877,11 @@ def main():
# in sudorule
if entry.host is not None:
host_del = gen_intersection_list(
entry.host, res_find.get("memberhost_host"))
entry.host, (
list(res_find.get("memberhost_host", []))
+ list(res_find.get("externalhost", []))
)
)
if entry.hostgroup is not None:
hostgroup_del = gen_intersection_list(
@@ -876,7 +895,11 @@ def main():
if entry.user is not None:
user_del = gen_intersection_list(
entry.user, res_find.get("memberuser_user"))
entry.user, (
list(res_find.get('memberuser_user', []))
+ list(res_find.get('externaluser', []))
)
)
if entry.group is not None:
group_del = gen_intersection_list(
@@ -911,8 +934,7 @@ def main():
# users list.
if entry.runasuser is not None:
runasuser_del = gen_intersection_list(
entry.runasuser,
(
entry.runasuser, (
list(res_find.get('ipasudorunas_user', []))
+ list(res_find.get('ipasudorunasextuser', []))
)

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

@@ -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
@@ -190,7 +190,7 @@ Variable | Description | Required
`ipaservers` | This group with the IPA master full qualified hostnames. (list of strings) | mostly
`ipareplicas` | Group of IPA replica hostnames. (list of strings) | yes
`ipaadmin_password` | The password for the IPA admin user (string) | mostly
`ipareplica_ip_addresses` | The list of master server IP addresses. (list of strings) | no
`ipareplica_ip_addresses` | The list of IPA replica IP addresses. (list of strings) | no
`ipareplica_domain` | The primary DNS domain of an existing IPA deployment. (string) | no
`ipaserver_realm` | The Kerberos realm of an existing IPA deployment. (string) | no
`ipaserver_hostname` | Fully qualified name of the server. (string) | no

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

@@ -47,7 +47,7 @@ options:
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
description: List of IPA replica IP addresses
type: list
elements: str
required: no

View File

@@ -47,7 +47,7 @@ options:
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
description: List of IPA replica IP addresses
type: list
elements: str
required: no

View File

@@ -49,7 +49,7 @@ options:
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
description: List of IPA replica IP addresses
type: list
elements: str
required: no

View File

@@ -47,7 +47,7 @@ options:
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
description: List of IPA replica IP addresses
type: list
elements: str
required: no

View File

@@ -47,7 +47,7 @@ options:
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
description: List of IPA replica IP addresses
type: list
elements: str
required: no

View File

@@ -38,7 +38,7 @@ short_description: IPA replica deployment tests
description: IPA replica deployment tests
options:
ip_addresses:
description: List of Master Server IP Addresses
description: List of IPA replica IP addresses
type: list
elements: str
required: no

View File

@@ -125,6 +125,7 @@
ipaclient_realm: "{{ result_ipareplica_test.realm | default(omit) }}"
ipaclient_servers: "{{ ipareplica_servers | default(omit) }}"
ipaclient_hostname: "{{ result_ipareplica_test.hostname }}"
ipaclient_ip_addresses: "{{ ipareplica_ip_addresses | default(omit) }}"
ipaclient_install_packages: "{{ ipareplica_install_packages }}"
when: not result_ipareplica_test.client_enrolled

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

@@ -23,7 +23,9 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type # pylint: disable=invalid-name
# pylint: disable=invalid-name
__metaclass__ = type
# pylint: enable=invalid-name
__all__ = ["IPAChangeConf", "certmonger", "sysrestore", "root_logger",
"ipa_generate_password", "run", "ScriptError", "services",

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

@@ -0,0 +1,65 @@
---
- name: Test remove certificate hold by removing it from CRL.
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipacert:
ipaadmin_password: SomeADMINpassword
tasks:
- name: Ensure test users are present
ipauser:
name: testuser
first: test
last: user
- name: Create user certificae CSR
ansible.builtin.shell:
cmd: |-
openssl req -newkey rsa:2048 -keyout /dev/null -nodes \
-subj /CN=testuser -reqexts IECUserRoles -config \
<(cat /etc/pki/tls/openssl.cnf; \
printf "[IECUserRoles]\n1.2.3.10.9.8=ASN1:UTF8String:Testing Cert")
args:
executable: /bin/bash
register: user_csr
- name: Request certificate with ipacert
ipacert:
csr: '{{ user_csr.stdout }}'
principal: testuser
state: requested
register: user_csr
failed_when: not user_csr.changed or user_csr.failed
- name: Revoke certifice with reason 6 (certificateHold)
ipacert:
serial_number: "{{ user_csr.certificate.serial_number }}"
revocation_reason: certificateHold
state: revoked
register: result
failed_when: not result.changed or result.failed
- name: Revoke certificate with reason 8 (removeFromCRL)
ipacert:
serial_number: "{{ user_csr.certificate.serial_number }}"
revocation_reason: removeFromCRL
state: revoked
register: result
failed_when: not result.changed or result.failed
- name: Revoke certificate with reason 8 (removeFromCRL), again
ipacert:
serial_number: "{{ user_csr.certificate.serial_number }}"
revocation_reason: removeFromCRL
state: revoked
register: result
failed_when: result.changed or result.failed
- name: Ensure test users are absent
ipauser:
name: testuser
state: absent

View File

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

View File

@@ -34,6 +34,16 @@
ipaapi_context: "{{ ipa_context | default(omit) }}"
emaildomain: ipa.test
- name: Ensure the default e-mail domain cannot be set to an invalid email domain.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
emaildomain: invalid@emaildomain
register: invalid_emaildomain
failed_when:
invalid_emaildomain.changed
or not (invalid_emaildomain.failed and "Invalid 'emaildomain' value:" in invalid_emaildomain.msg)
- name: Set default shell to '/bin/sh'
ipaconfig:
ipaadmin_password: SomeADMINpassword

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,114 +1,204 @@
---
- name: Find trust
hosts: ipaserver
become: true
- 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: 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 tests groups are absent
ipagroup:
name:
- extgroup
- extgroup_members
state: absent
- name: Execute group tests if trust test environment is supported
when: trust_test_is_supported | default(false)
block:
- name: Add nonposix group.
- name: Ensure nonposix group is present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
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:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
register: result
failed_when: result.failed or not result.changed
- name: Add AD users to group
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or not result.changed
- name: Add AD users to group, again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external_member: "AD\\Domain Users"
nonposix: true
register: result
failed_when: result.failed or result.changed
- name: Remove external group
- name: Ensure nonposix group is external
ipagroup:
name: extgroup
external: true
register: result
failed_when: result.failed or not result.changed
- name: Ensure nonposix group has AD users
ipagroup:
name: extgroup
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure nonposix group has AD users, again
ipagroup:
name: extgroup
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure nonposix group is absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
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:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
external: yes
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:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
external: yes
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:
ipaadmin_password: SomeADMINpassword
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:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, and add users.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, and add users, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
external_member: "AD\\Domain Users"
state: absent
register: result
failed_when: result.failed or result.changed
- name: Cleanup environment.
- name: Ensure nonposix group is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: true
register: result
failed_when: result.failed or not result.changed
- name: Ensure group is external, and has AD users.
ipagroup:
name: extgroup
external: true
external_member: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure group is external, and has AD alternate users.
ipagroup:
name: extgroup
external: true
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
- name: Ensure external group for external member exist
ipagroup:
name: extgroup_members
external: true
register: result
failed_when: result.failed or not result.changed
- name: Ensure external group members are present
ipagroup:
name: extgroup_members
external_member: "{{ ad_user }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Ensure external group members are present, again
ipagroup:
name: extgroup_members
external_member: "{{ ad_user }}"
action: member
register: result
failed_when: result.failed or result.changed
- name: Ensure external group members are absent
ipagroup:
name: extgroup_members
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_user }}"
action: member
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure tests groups are absent
ipagroup:
name:
- extgroup
- extgroup_members
state: absent

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

@@ -0,0 +1,94 @@
---
- name: Test correct handling of users and hosts lists on ipasudorule
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipahost:
ipaadmin_password: SomeADMINpassword
ipasudorule:
ipaadmin_password: SomeADMINpassword
tasks:
- name: Ensure test state is valid
block:
- name: Ensure users are present
ipauser:
users:
- name: user_s1
first: user
last: s1
- name: user_s2
first: user
last: s2
- name: Ensure hosts are present
ipahost:
hosts:
- name: mytesthost1.ipadomain.test
force: true
- name: mytesthost1a.ipadomain.test
force: true
- name: Ensure sudorule_5a is absent
ipasudorule:
name: sudorule_5a
state: absent
- name: Ensule sudorule_5a is present with host masks and external hosts
ipasudorule:
name: sudorule_5a
hostmask: [192.168.221.0/24, 192.168.110.0/24]
host: [mytesthost1.ipa.test, mytesthost2.ipa.test]
user: [user_s1, user_s2]
- name: Ensure that sudorule remain present after remove their members(using action member).
block:
- name: Ensure sudorules members are absent
ipasudorule:
name: sudorule_5a
hostmask: 192.168.221.0/24
user: "user_s1"
host: "mytesthost1.ipa.test"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules members are absent, again
ipasudorule:
name: sudorule_5a
hostmask: 192.168.221.0/24
user: "user_s1"
host: "mytesthost1.ipa.test"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Check if other sudorule members are still present.
ipasudorule:
name: sudorule_5a
hostmask: 192.168.110.0/24
user: "user_s2"
host: "mytesthost2.ipa.test"
action: member
check_mode: true
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Ensure test sudorule is absent
ipasudorule:
name: sudorule_5a
state: absent
- name: Ensure test hosts are absent
ipahost:
name: [mytesthost1.ipa.test, mytesthost1a.ipa.test]
state: absent
- name: Ensure test users are absent
ipauser:
name: [user_s1, user_s2]
state: absent
...

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

@@ -140,21 +140,18 @@ sed -i -e "s/ansible.module_utils.ansible_freeipa_module/ansible_collections.${c
python utils/create_action_group.py "meta/runtime.yml" "$collection_prefix"
(cd plugins/module_utils && {
ln -sf ../../roles/*/module_utils/*.py .
})
mv roles/*/module_utils/*.py plugins/module_utils/
rmdir roles/*/module_utils
(cd plugins/modules && {
sed -i -e "s/ansible.module_utils.ansible_ipa_/ansible_collections.${collection_prefix}.plugins.module_utils.ansible_ipa_/" ../../roles/*/library/*.py
ln -sf ../../roles/*/library/*.py .
})
sed -i -e "s/ansible.module_utils.ansible_ipa_/ansible_collections.${collection_prefix}.plugins.module_utils.ansible_ipa_/" roles/*/library/*.py
mv roles/*/library/*.py plugins/modules/
rmdir roles/*/library
# There are no action plugins anymore in the roles, therefore this section
# is commneted out.
#[ ! -x plugins/action ] && mkdir plugins/action
#(cd plugins/action && {
# ln -sf ../../roles/*/action_plugins/*.py .
#})
#mv roles/*/action_plugins/*.py plugins/action/
#rmdir roles/*/action_plugins
# Adapt inventory plugin and inventory plugin README
echo "Fixing inventory plugin and doc..."
@@ -181,19 +178,11 @@ find plugins/modules -name "*.py" -print0 |
done
echo -e "\033[AFixing examples in plugins/modules... \033[32;1mDONE\033[0m"
echo "Fixing examples in roles/*/library..."
find roles/*/library -name "*.py" -print0 |
while IFS= read -d '' -r line; do
python utils/galaxyfy-module-EXAMPLES.py "$line" \
"ipa" "$collection_prefix"
done
echo -e "\033[AFixing examples in roles/*/library... \033[32;1mDONE\033[0m"
echo "Fixing playbooks in roles/*/tasks..."
for line in roles/*/tasks/*.yml; do
python utils/galaxyfy-playbook.py "$line" "ipa" "$collection_prefix"
done
echo -e "\033[AFixing playbooks in roles/*tasks... \033[32;1mDONE\033[0m"
echo -e "\033[AFixing playbooks in roles/*/tasks... \033[32;1mDONE\033[0m"
echo "Fixing playbooks in playbooks..."
find playbooks -name "*.yml" -print0 |

View File

@@ -113,7 +113,7 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list
gen_intersection_list, ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -124,7 +124,7 @@ def find_$name(module, name):
"""Find if a $name with the given name already exist."""
try:
_result = module.ipa_command("$name_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if $name name is not found.
return None
return _result["result"]

View File

@@ -89,7 +89,7 @@ RETURN = """
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
IPAAnsibleModule, compare_args_ipa, ipalib_errors
from ansible.module_utils import six
if six.PY3:
@@ -100,7 +100,7 @@ def find_$name(module, name):
"""Find if a $name with the given name already exist."""
try:
_result = module.ipa_command("$name_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
except ipalib_errors.NotFound:
# An exception is raised if $name name is not found.
return None
return _result["result"]