Compare commits

...

66 Commits

Author SHA1 Message Date
Thomas Woerner
1930d8c8be Merge pull request #1168 from rjeffman/dev_reproduce_upstream_groups
Reproduce upstream CI groups in developer's machine
2023-11-24 15:39:47 +01:00
Thomas Woerner
1837ee662c Merge pull request #1104 from rjeffman/ci_parallel_image_build
upstream CI: Build containers in parallel jobs
2023-11-24 14:50:44 +01:00
Thomas Woerner
26e171df79 Merge pull request #1170 from rjeffman/ci_ansible_future
Update ansible-lint and pylint versions
2023-11-24 14:46:22 +01:00
Thomas Woerner
01440e3c04 Merge pull request #1173 from rjeffman/ipahost_fix_dnsrecords
ipahost: Remove dangling dns records during test setup
2023-11-24 14:44:19 +01:00
Rafael Guterres Jeffman
2426e04c22 Merge pull request #1176 from t-woerner/idoverrideX_del_without_delete_continue
idoverride{user,group}: Fix delete_continue with state absent
2023-11-24 09:02:05 -03:00
Thomas Woerner
92e44f6a6c idoverride{user,group}: Fix delete_continue with state absent
All tasks for idoverrideuser and idoverridegroup with state absent
failed with "'continue' is required" when delete_continue was not set.

This happended as delete_continue was internally None and continue: None
was provided to the API.

The fix is simply to use '"continue": delete_continue or False' so that
continue is set to False in this case.
2023-11-16 13:47:04 +01:00
Rafael Guterres Jeffman
16c8ee87e9 ipahost: Remove dangling dns records during test setup
When testing ipahost through the test playbooks, if there are previous
DNS A/AAAA records, the test fails due to a false positive idempotence
issue.

This patch ensures that all DNS records for the test hosts are absent
before test execution.

This issue could be seen in the 2023-11-06 Azure Nightly pipeline
execution.
2023-11-10 20:26:51 -03:00
Rafael Guterres Jeffman
3109e9d1bc utils/run-tests.sh: Replicate Azure's test grouping
When running ansible-freeipa's Azure pipelines for nightly and weekly
tests, due to the amount of tests to execute, tests are grouped and
executed in parallel jobs.

Due to a still unkonwn issue, depending on the order the tests are
executed, some random failures may occur and debugging them is hard due
to current implementation of the tests.

This patch adds support for replicating the tests of a specific Azure
test group once the seed used to create groups and the group number are
provided, allowing the test failures to be replicated on the developer's
workstation where it can be more easily debugged.

A new option is added to 'utils/run-tests.sh', '-A SEED.G' that is used
to define the seed and group to replicate the tests. The seed is a date,
with the format "YYYYMMDD", so, for example '-A 20230611.2' would
execute the same tests, in the same order as the second group of tests
for date 2023-06-11. To aid in usability 'YYYY-MM-DD' may also be used.

When using '-A' neither '-s' (test suites) or specific tests (positional
arguments) can be used.

Also, to help fixing tests, an option to stop the tests on the first
test failure ('-x') was added to the script.
2023-11-09 12:36:59 -03:00
Rafael Guterres Jeffman
b457de545d Update ansible-lint and pylint versions
ansible-lint 6.21+ and pylint 3.0+ will be required for Ansible
collections to be approved on Ansible Galaxy.

This patch updates pre-commit and upstream linters to use the required
versions.
2023-11-08 15:11:02 -03:00
Rafael Guterres Jeffman
f1a6f44477 Merge pull request #1158 from t-woerner/idview_fail_to_apply_invalid_hosts
ipaidview: Fail to apply unknown (invalid) hosts
2023-10-22 22:43:03 -03:00
Rafael Guterres Jeffman
1dbe19cefb Merge pull request #1156 from t-woerner/hbacsvcgroup_remove_oobsolete_result_handler
hbacsvcgroup: Remove obsolete result_handler
2023-10-22 22:42:06 -03:00
Rafael Guterres Jeffman
7982fad342 Merge pull request #1155 from t-woerner/hbacrule_with_svcgroup_Sudo
hbacrule: Fix use of builtin sudo hbacsvcgroup
2023-10-22 22:41:18 -03:00
Thomas Woerner
212719496c ipaidview: Fail to apply unknown (invalid) hosts
The task to apply an unknown (invalid) host to an idview was not failing
as expected and only reported no change.

A new host verification step has been added to fail before trying to
apply invalid hosts. unapplying an invalid host is not failing as the
invalid host is indeed not applied.
2023-10-21 01:10:13 +02:00
Thomas Woerner
3de6f9146e hbacsvcgroup: Remove obsolete result_handler
The result_handler is not needed anymore as the idempotency issues with
members have been fixed already for this module.

Related: #685 hbacsvcgroup: Fix member management idempotence issues.
2023-10-21 01:09:21 +02:00
Thomas Woerner
48f2ef88a4 hbacrule: Fix use of builtin sudo hbacsvcgroup
hbacsvcgroup names are converted to lower case while creation with
hbacsvcgroup_add.

The hbacsvcgroup for sudo is builtin with the name "Sudo" though. This
breaks the lower case comparison. Therefore all memberservice_hbacsvcgroup
items are converted to lower case if "Sudo" is in the list.
2023-10-21 01:08:44 +02:00
Rafael Guterres Jeffman
6845acd596 upstream CI: Build containers in parallel jobs
In the current build container pipeline, all steps are serialized in a
single job, and if one of the jobs fail to build, due to broken
dependent image, or some Azure glitch, like slow connection, the only
way to rebuild the failed container is to rebuild all containers.

By building containers in parallel jobs, if a container fails to build
it is possible to restart only the failed job.
2023-10-20 13:44:09 -03:00
Thomas Woerner
ba7bf0f6cd Merge pull request #1148 from rjeffman/fix_checkpr_test_selection
upstream CI: Fix test selection for CheckPR pipeline.
2023-10-20 16:35:03 +02:00
Rafael Guterres Jeffman
fe2d17e4df upstream ci: Run PR tests using a single job.
The usual scenario for PR checks is to execute only a few tests, and
searching for the results in several jobs makes it harder to find
issues.

By using a single job run the tests would take some more time to
complete, although not much, as only a small subset is executed, and
test verification would be easier and less error prone.
2023-10-19 09:41:55 -03:00
Rafael Guterres Jeffman
319a0d3d86 upstream ci: Use a single random seed for spliting tests
Dependind on how long it took for the jobs to start, a different seed
would be used to group tests and tests could either repeat or not be
selected at all.

By using a seed based on the day the test run reduces the chance of
using different random seeds, and still allow for the tests to be
executed in a different order.

The execution in different order is important to identify tests that
work or fail only if executed after other tests.
2023-10-19 09:41:55 -03:00
Rafael Guterres Jeffman
c71a2b33dd upstream CI: Fix test selection for CheckPR pipeline.
Due to an error on processing Ansible key 'import_tasks' the script that
creates a list of modules to test is broken making some modules to be
not tested.

By fixing the handling of 'import_tasks' and module import, the list is
correct again and the list of modules to be tested now include the ones
which depend on the modified module.
2023-10-19 09:41:55 -03:00
Thomas Woerner
02223dfb67 Merge pull request #1159 from rjeffman/ci_pin_ansible_lint
upstream CI: Pin ansible-lint version to 6.20 series
2023-10-19 13:18:27 +02:00
Rafael Guterres Jeffman
5731a1539b upstream CI: Pin ansible-lint version to 6.20 series
The release version 6.21.0 of ansible-lint introduced a bug that breaks
the reporting of 'warning' messages. [1]

This patch pins ansible-lint version to the latest one in the 6.20
series, so that it can still be used to check pull requests.

[1]: https://github.com/ansible/ansible-lint/issues/3853
2023-10-18 15:36:16 -03:00
Thomas Woerner
ee7354230b Merge pull request #1157 from rjeffman/ci_fix_docker_install
upstream CI: Pin Python version to 3.11
2023-10-18 16:14:49 +02:00
Rafael Guterres Jeffman
4bb40f3397 Merge pull request #1146 from t-woerner/update_ansible-freeipa.spec.in_for_doverridegroup
utils/ansible-freeipa.spec.in: Add ref for idoverridegroup management
2023-10-17 17:05:39 -03:00
Rafael Guterres Jeffman
55b8729c52 upstream CI: Pin Python version to 3.11
Azure Ubuntu images have Python 3.12 available, and as we did not pin
the requested Python version, the latest available one was used, causing
image preparation and tests to fail.

This patch pins Python version to 3.11 until test can be executed with
Python 3.12 and later.
2023-10-17 16:32:37 -03:00
Rafael Guterres Jeffman
539ace413d Merge pull request #1105 from t-woerner/new_idp_module
New idp management module
2023-09-27 12:12:14 -03:00
Thomas Woerner
0c20b34d28 utils/ansible-freeipa.spec.in: Add ref for idoverridegroup management
The idoverridegroup management reference has been added to the
description.
2023-09-27 14:43:11 +02:00
Thomas Woerner
f9ff41320f New idp management module
There is a new idp management module placed in the plugins folder:

    plugins/modules/ipaidp.py

The idp module allows to ensure presence or absence of external Identity
Providers.

Here is the documentation for the module:

    README-idp.md

New idp example playbooks:

    playbooks/idp/idp-present.yml
    playbooks/idp/idp-absent.yml

New tests for the module:

    tests/idp/test_idp.yml
    tests/idp/test_idp_client_context.yml
2023-09-27 10:52:55 +02:00
Thomas Woerner
69c6b4d644 Merge pull request #1145 from rjeffman/revert_ansible_2_9
Revert "upstream ci: Run nightly tests against Ansible 2.9"
2023-09-26 17:41:08 +02:00
Rafael Guterres Jeffman
b63716b724 Revert "upstream ci: Run nightly tests against Ansible 2.9"
Most of our usptream CI test imagens do not handle Ansible 2.9 so, this
cange is being reverted.

This reverts commit 34654d1090.
2023-09-26 11:25:58 -03:00
Thomas Woerner
3cf138674b Merge pull request #1144 from rjeffman/upstream_ci_ansible_2_9
Ensure CI runs against the oldest supported Ansible versions.
2023-09-25 16:04:59 +02:00
Thomas Woerner
12e0d110f6 Merge pull request #1112 from rjeffman/future_pylint
Bump linter versions.
2023-09-25 16:02:53 +02:00
Rafael Guterres Jeffman
34654d1090 upstream ci: Run nightly tests against Ansible 2.9
Recently it was announced that Ansible 2.9 will be supported for some
time, and this patch ensures that we run the nightly tests against this
version of Ansible.
2023-09-19 15:54:38 -03:00
Rafael Guterres Jeffman
72d3ab8e04 upstream ci: Run PR checks against the oldest supported ansible-core
Recently, a change in the deployment roles forced the change to the
minimum version of ansible-core, and the change was unnoticed until
reported.

With this patch, we ensure all PRs checks are executed against the
minimun supported ansible-core version, so we can ensure that both
documentation and role metadata are correct and still valid.
2023-09-19 15:54:38 -03:00
Rafael Guterres Jeffman
fb75aed663 Merge pull request #1141 from t-woerner/new_idoverridegroup_module
New idoverridegroup management module.
2023-09-18 11:05:30 -03:00
Thomas Woerner
6f5bb9eebf New idoverridegroup management module.
There is a new idoverridegroup management module placed in the plugins
folder:

    plugins/modules/ipaidoverridegroup.py

The idoverridegroup module allows to ensure presence and absence of
idoverrides for groups.

Here is the documentation for the module:

    README-idoverridegroup.md

New example playbooks have been added:

    playbooks/idoverridegroup/idoverridegroup-absent.yml
    playbooks/idoverridegroup/idoverridegroup-present.yml

New tests for the module can be found at:

    tests/idoverridegroup/test_idoverridegroup.yml
    tests/idoverridegroup/test_idoverridegroup_client_context.yml
2023-09-18 15:17:08 +02:00
Rafael Guterres Jeffman
e5b2c122ce Merge pull request #1139 from t-woerner/new_idoverrideuer_module
New idoverrideuser management module.
2023-09-16 09:03:48 -03:00
Thomas Woerner
c0692e1746 New idoverrideuser management module.
There is a new idoverrideuser management module placed in the plugins
folder:

    plugins/modules/ipaidoverrideuser.py

The idoverrideuser module allows to ensure presence and absence of
idoverrides for users and certificate members.

Here is the documentation for the module:

    README-idoverrideuser.md

New example playbooks have been added:

    playbooks/idoverrideuser/idoverrideuser-absent.yml
    playbooks/idoverrideuser/idoverrideuser-certificate-absent.yml
    playbooks/idoverrideuser/idoverrideuser-certificate-present.yml
    playbooks/idoverrideuser/idoverrideuser-present.yml

New tests for the module can be found at:

    tests/idoverrideuser/test_idoverrideuser.yml
    tests/idoverrideuser/test_idoverrideuser_client_context.yml
2023-09-15 18:35:21 +02:00
Rafael Guterres Jeffman
2d079c8eec Merge pull request #1142 from t-woerner/Do_not_use_del_os.environ
Do not use "del os.environ" as the variable might not exist
2023-09-14 11:19:03 -03:00
Thomas Woerner
b70a1ecf61 Do not use "del os.environ" as the variable might not exist
The use of del os.environ assumes that the environment variable exists.
If the variable does not exist, this call will result in a traceback.
The solution is to use os.environ.pop(VARIABLE, None) instead.

This is the ansible-freeipa fix for https://pagure.io/freeipa/issue/9446
(Nightly test failure for replica installation with --setup-ca)
2023-09-14 15:20:37 +02:00
Rafael Guterres Jeffman
7cb5e481e5 Merge pull request #1140 from t-woerner/new_module_template_fixes
new_module template fixes
2023-09-13 11:07:02 -03:00
Thomas Woerner
60593b7dd3 utils/templates/ipamodule*.py.in: Fix superfluous type in argument spec
The type was given twice for state and action argument specs. This has
been fixed.
2023-09-13 13:20:47 +02:00
Thomas Woerner
e84ed3b6ba utils/templates/test_module_client_context.yml.in: Fix FQDN issue
Fixes left over FQDN issue for include_tasks.
2023-09-13 13:09:24 +02:00
Rafael Guterres Jeffman
6e1f9f1a72 pylint: Fix redefined-builtin 2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
46a307aaeb pylint: Fix unused-argument 2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
d8f8211a1c ci: Bump pylint version
Change pylint version to match latest version on Fedora 38.
2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
34daa992f5 development: Bump versions of development checks
Update versions for linters and pre-commit checks, and fix ansible-lint
execution.
2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
07c1a5ee61 pylint: Unnecessary parens after '=' keyword
This patch removes unnecessary usage of parens on attributions.
2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
63d0272385 Change 'Exception' to 'RuntimeError' when FreeIPA version is too old
Changing the use of 'Exception' to 'RuntimeError' has the benefits of
making the error more specific and meaningful for what is being reported
and to remove warnings from linters (pylint).

The same change is applied to all deployment roles.
2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
d0a8005a7f pylint: Disable broad exception warnings
In recent pylint versions, use of broad exceptions for both raise and
try/except blocks raise a linter warning. As its use is justifiable in
the case of ipavault, the warnings are disabled where they occur.
2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
24efad73fa pylint: Fix warning 'unnecessary "else" after "return"'
Recent pylint versions warn against the use of an 'else' in a
'try-except' block if using a 'return' on the 'except' part is is the
idom used by ansible-freeipa when retrieving IPA data objects.

This change removes the usage of the 'else:' in such cases, and modify
the templates so that new modules do not have the same issue in the
future.
2023-09-11 12:01:17 -03:00
Rafael Guterres Jeffman
fd1352ad7e pylint: Disable warning when using non-literal dict
Recent pylint versions warns when a dictionaire is created using
'dict()' instead of '{...}'. Using 'dict()' in ansible-freeipa modules
actually enhances readability, so this change disables the check for
'use-dict-literal' in pylint.
2023-09-11 12:01:17 -03:00
Thomas Woerner
de38e8f0bc Merge pull request #1138 from rjeffman/fix_spec_update_modules
spec file: Updated list of modules
2023-09-11 10:55:31 +02:00
Rafael Guterres Jeffman
847ae2a374 spec file: Updated list of modules
Current spec file template was missing certificate, netgroup and
idview modules.
2023-09-08 11:21:33 -03:00
Thomas Woerner
bcee9aba92 Merge pull request #1136 from rjeffman/bump_ansible_version_2.13
Bump Ansible version to 2.13
2023-09-08 15:47:57 +02:00
Rafael Guterres Jeffman
c34c66fa79 ansible-freeipa: Bump minimum supported Ansible version to 2.13
As ansible-freeipa roles does not support Ansible 2.8, bump the
collection version to the currently oldest supported Ansible version
available, 2.13.
2023-09-08 09:59:11 -03:00
Rafael Guterres Jeffman
0a3cd06c6e README-*: Bump minimum supported Ansible version to 2.13
As ansible-freeipa roles do not support version 2.8 anymore, change the
minimum supported version to 2.13, which is the currently minimum
available and supported Ansible version.

This patch fixes documentation on all plugin READMEs, spec file and
module templates.
2023-09-08 09:59:11 -03:00
Rafael Guterres Jeffman
b5b22c3f7e roles: Bump minimum Ansible version to 2.13
Currently, the minimum supported Ansible version is 2.13, and
ansible-freeipa roles does not work with any version less than 2.9,
altough ansible-freeipa documentation states that the minimum version to
use is 2.8.

This patch fixes documentation and roles metadata to require that the
minimum Ansible version used is 2.13.
2023-09-08 09:59:11 -03:00
Thomas Woerner
7ee385ee02 Merge pull request #1131 from rjeffman/roles_update_supported_distros
Updated supported distros
2023-09-07 13:05:24 +02:00
Thomas Woerner
7d9e4da9df Merge pull request #1120 from rjeffman/ci_fix_sanity_test_ansible_lint
upstream ci: fix sanity test ansible lint failures
2023-09-07 13:03:53 +02:00
Thomas Woerner
0a20b5902d Merge pull request #1133 from rjeffman/testday_1
ipacert: Fix revocation example playbook on README
2023-09-07 13:02:13 +02:00
Rafael Guterres Jeffman
be9a2db404 Merge pull request #1134 from t-woerner/new_idview_module
New idview management module.
2023-09-06 09:53:23 -03:00
Thomas Woerner
ba4a360520 New idview management module.
There is a new idview management module placed in the plugins folder:

    plugins/modules/ipaidview.py

The idview module allows to ensure presence and absence of idviews and
idview host members.

Here is the documentation for the module:

    README-idview.md

New example playbooks have been added:

    playbooks/idview/idview-absent.yml
    playbooks/idview/idview-host-applied.yml
    playbooks/idview/idview-host-unapplied.yml
    playbooks/idview/idview-present.yml

New tests for the module can be found at:

    tests/idview/test_idview.yml
    tests/idview/test_idview_client_context.yml
2023-09-06 12:40:32 +02:00
Rafael Guterres Jeffman
3534fcdce7 ansible-lint: Use the same command line as galaxy-importer
Currently, there is a hard coded timeout in galaxy-importer that
prevents larger collections to execute the ansible-lint step [1].

This patch modifies the calls to ansible-lint on development tools and
upstream CI to use the same arguments as galaxy-importer and disables
the execution of the ansible-lint step for the Ansible's sanity test.

Requested ansible-lint version for tools is also updated, as a more
recent one is required.

This change will not allow development using an environment using Python
2.7, due to newer ansible-lint requirements. Roles and modules tests
against target nodes using Python 2.7 is still possible.

[1]: https://github.com/ansible/galaxy-importer/pull/231
2023-09-05 14:10:09 -03:00
Rafael Guterres Jeffman
f0f21fc8aa ipacert: Fix revocation example playbook on README
The revocation example playbook on README was wrong as it didn't have a
'reason' set, and the parameter must be used with 'state: revoked'.

This patch fixes the example and adds a new example using a reason
mnemonic instead of a reason number.
2023-08-24 08:50:18 -03:00
Rafael Guterres Jeffman
5ed96eda05 Updated supported distros
Updated all roles README files to add supported distros, as CentOS
Stream is supported (both 8 and 9) and also Debian clients.
2023-08-23 15:35:04 -03:00
134 changed files with 4935 additions and 239 deletions

View File

@@ -16,10 +16,10 @@ jobs:
python-version: "3.x"
- name: Run ansible-lint
run: |
pip install "ansible-core >=2.15,<2.16" ansible-lint
pip install "ansible-core>=2.16,<2.17" 'ansible-lint>=6.21'
utils/build-galaxy-release.sh -ki
cd .galaxy-build
ansible-lint
ansible-lint --profile production --exclude tests/integration/ --exclude tests/unit/ --parseable --nocolor
yamllint:
name: Verify yamllint
@@ -76,7 +76,7 @@ jobs:
python-version: "3.x"
- name: Run pylint
run: |
pip install pylint==2.14.4 wrapt==1.14.0
pip install 'pylint>=3.0'
pylint plugins roles --disable=import-error
shellcheck:

View File

@@ -1,22 +1,32 @@
---
repos:
- repo: https://github.com/ansible/ansible-lint.git
rev: v6.6.1
rev: v6.22.0
hooks:
- id: ansible-lint
always_run: false
pass_filenames: true
files: \.(yaml|yml)$
exclude: /env[^/]*.(yaml|yml)$
entry: |
env ANSIBLE_LIBRARY=./plugins/modules ANSIBLE_MODULE_UTILS=./plugins/module_utils ANSIBLE_DOC_FRAGMENT_PLUGINS=./plugins/doc_fragments ansible-lint
entry: |-
env
ANSIBLE_LIBRARY=./plugins/modules
ANSIBLE_MODULE_UTILS=./plugins/module_utils
ANSIBLE_DOC_FRAGMENT_PLUGINS=./plugins/doc_fragments
ansible-lint
--offline
--profile production
--exclude tests/integration/
--exclude tests/unit/
--parseable
--nocolor
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.28.0
rev: v1.32.0
hooks:
- id: yamllint
files: \.(yaml|yml)$
- repo: https://github.com/pycqa/flake8
rev: 5.0.3
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/pydocstyle
@@ -24,7 +34,7 @@ repos:
hooks:
- id: pydocstyle
- repo: https://github.com/pycqa/pylint
rev: v2.14.4
rev: v3.0.2
hooks:
- id: pylint
args:

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipaautomountkey module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipaautomountlocation module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipaautomountmap module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -25,7 +25,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
* Some tool to generate a certificate signing request (CSR) might be needed, like `openssl`.
**Node**
@@ -77,6 +77,23 @@ Example playbook to revoke an existing certificate:
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 123456789
reason: 5
state: revoked
```
When revoking a certificate a mnemonic can also be used to set the revocation reason:
```yaml
---
- name: Revoke certificate
hosts: ipaserver
tasks:
- name Revoke a certificate
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 123456789
reason: cessationOfOperation
state: revoked
```

View File

@@ -25,7 +25,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -23,7 +23,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipadnsforwardzone module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -23,7 +23,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**

View File

@@ -29,7 +29,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -26,7 +26,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

233
README-idoverridegroup.md Normal file
View File

@@ -0,0 +1,233 @@
Idoverridegroup module
============
Description
-----------
The idoverridegroup module allows to ensure presence and absence of idoverridegroups and idoverridegroup members.
Use Cases
---------
With idoverridegroup it is possible to manage group attributes within ID views. These attributes are for example the group name or gid.
Features
--------
* Idoverridegroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidoverridegroup module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure test group test_group is present in idview test_idview
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
```
Example playbook to make sure test group test_group is present in idview test_idview with description
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with description
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: "test_group description"
```
Example playbook to make sure test group test_group is present in idview test_idview without description
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview without description
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: ""
```
Example playbook to make sure test group test_group is present in idview test_idview with internal name test_123_group
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with internal name test_123_group
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: test_123_group
```
Example playbook to make sure test group test_group is present in idview test_idview without internal name
```yaml
---
- name: Playbook to manage idoverridegroup
- name: Ensure test group test_group is present in idview test_idview without internal name
hosts: ipaserver
become: false
tasks:
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: ""
```
Example playbook to make sure test group test_group is present in idview test_idview with gid 20001
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with gid 20001
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: 20001
```
Example playbook to make sure test group test_group is present in idview test_idview without gid
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview without gid
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: ""
```
Example playbook to make sure test group test_group is present in idview test_idview with enabling falling back to AD DC LDAP when resolving AD trusted objects. (For two-way trusts only.)
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with fallback_to_ldap enabled
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
fallback_to_ldap: true
```
Example playbook to make sure test group test_group is absent in idview test_idview
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is absent in idview test_idview
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
continue: true
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
`idview` \| `idviewcn` | The doverridegroup idview string. | yes
`anchor` \| `ipaanchoruuid` | The list of anchors to override. | yes
`description` \| `desc` | Description | no
`name` \| `group_name` \| `cn` | The group. | no
`gid` \| `gidnumber` | Group ID Number (int or "") | no
`fallback_to_ldap` | Allow falling back to AD DC LDAP when resolving AD trusted objects. For two-way trusts only. | no
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

503
README-idoverrideuser.md Normal file
View File

@@ -0,0 +1,503 @@
Idoverrideuser module
============
Description
-----------
The idoverrideuser module allows to ensure presence and absence of idoverrideusers and idoverrideuser members.
Use Cases
---------
With idoverrideuser it is possible to manage user attributes within ID views. These attributes are for example the login name, home directory, certificate for authentication or SSH keys.
Features
--------
* Idoverrideuser management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidoverrideuser module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure test user test_user is present in idview test_idview
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview.
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
```
Example playbook to make sure test user test_user is present in idview test_idview with description
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with description
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: "test_user description"
```
Example playbook to make sure test user test_user is present in idview test_idview without description
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without description
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with internal name test_123_user
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with internal name test_123_user
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: test_123_user
```
Example playbook to make sure test user test_user is present in idview test_idview without internal name
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without internal name
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with uid 20001
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with uid 20001
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: 20001
```
Example playbook to make sure test user test_user is present in idview test_idview without uid
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without uid
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with gecos "Gecos Test"
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with gecos "Gecos Test"
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: Gecos Test
```
Example playbook to make sure test user test_user is present in idview test_idview without gecos
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without gecos
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with gidnumber
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with gidnumber
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: 20001
```
Example playbook to make sure test user test_user is present in idview test_idview without gidnumber
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without gidnumber
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with homedir /Users
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with homedir /Users
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: /Users
```
Example playbook to make sure test user test_user is present in idview test_idview without homedir
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without homedir
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with shell
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with shell
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: /bin/someshell
```
Example playbook to make sure test user test_user is present in idview test_idview without shell
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without shell
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with sshpubkey
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with sshpubkey
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey:
- ssh-rsa AAAAB3NzaC1yc2EAAADAQABAAABgQCqmVDpEX5gnSjKuv97Ay ...
```
Example playbook to make sure test user test_user is present in idview test_idview without sshpubkey
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without sshpubkey
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey: []
```
Example playbook to make sure test user test_user is present in idview test_idview with 1 certificate
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with 1 certificate
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
```
Example playbook to make sure test user test_user is present in idview test_idview with 3 certificate members
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with 3 certificate members
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
```
Example playbook to make sure test user test_user is present in idview test_idview without 2 certificate members
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without 2 certificate members
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
```
Example playbook to make sure test user test_user is present in idview test_idview without certificates
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without certificates
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate: []
```
Example playbook to make sure test user test_user is present in idview test_idview with enabling falling back to AD DC LDAP when resolving AD trusted objects. (For two-way trusts only.)
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with fallback_to_ldap enabled
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
fallback_to_ldap: true
```
Example playbook to make sure test user test_user is absent in idview test_idview
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is absent in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
continue: true
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
`idview` \| `idviewcn` | The doverrideuser idview string. | yes
`anchor` \| `ipaanchoruuid` | The list of anchors to override. | yes
`description` \| `desc` | Description | no
`name` \| `login` | The user (internally uid) | no
`uid` \| `uidnumber` | User ID Number (int or "") | no
`gecos` | GECOS | no
`gidnumber` | Group ID Number (int or ""). | no
`homedir` \| `homedirectory` | Home directory. | no
`shell` \| `loginshell` | Login shell. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
`certificate` \| `usercertificate` | List of Base-64 encoded user certificates. This variable can also be used with `action: member`. | no
`fallback_to_ldap` | Allow falling back to AD DC LDAP when resolving AD trusted objects. For two-way trusts only. | no
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`nomembers` \| `no_members` | Suppress processing of membership attributes. Valid only if `state` is `absent`. | no
`action` | Work on idoverrideuser or member level. It can be on of `member` or `idoverrideuser` and defaults to `idoverrideuser`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

192
README-idp.md Normal file
View File

@@ -0,0 +1,192 @@
Idp module
============
Description
-----------
The idp module allows to ensure presence and absence of idps.
Features
--------
* Idp management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidp module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure keycloak idp my-keycloak-idp is present:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure keycloak idp my-keycloak-idp is present
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
provider: keycloak
organization: main
base_url: keycloak.idm.example.com:8443/auth
client_id: my-client-id
```
Example playbook to make sure keycloak idp my-keycloak-idp is absent:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure keycloak idp my-keycloak-idp is absent
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
delete_continue: true
state: absent
```
Example playbook to make sure github idp my-github-idp is present:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure github idp my-github-idp is present
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-github-idp
provider: github
client_id: my-github-client-id
```
Example playbook to make sure google idp my-google-idp is present using provider defaults without specifying provider:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure google idp my-google-idp is present using provider defaults without specifying provider
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
auth_uri: https://accounts.google.com/o/oauth2/auth
dev_auth_uri: https://oauth2.googleapis.com/device/code
token_uri: https://oauth2.googleapis.com/token
keys_uri: https://www.googleapis.com/oauth2/v3/certs
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
client_id: my-google-client-id
scope: "openid email"
idp_user_id: email
```
Example playbook to make sure google idp my-google-idp is present using provider:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure google idp my-google-idp is present using provider
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
provider: google
client_id: my-google-client-id
```
Example playbook to make sure idps my-keycloak-idp, my-github-idp and my-google-idp are absent:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
ipaidp:
ipaadmin_password: SomeADMINpassword
name:
- my-keycloak-idp
- my-github-idp
- my-google-idp
delete_continue: true
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | false
`name` \| `cn` | The list of idp name strings. | yes
auth_uri \| ipaidpauthendpoint | OAuth 2.0 authorization endpoint string. | no
dev_auth_uri \| ipaidpdevauthendpoint | Device authorization endpoint string. | no
token_uri \| ipaidptokenendpoint | Token endpoint string. | no
userinfo_uri \| ipaidpuserinfoendpoint | User information endpoint string. | no
keys_uri \| ipaidpkeysendpoint | JWKS endpoint string. | no
issuer_url \| ipaidpissuerurl | The Identity Provider OIDC URL string. | no
client_id \| ipaidpclientid | OAuth 2.0 client identifier string. | no
secret \| ipaidpclientsecret | OAuth 2.0 client secret string. | no
scope \| ipaidpscope | OAuth 2.0 scope string. Multiple scopes separated by space. | no
idp_user_id \| ipaidpsub | Attribute string for user identity in OAuth 2.0 userinfo. | no
provider \| ipaidpprovider | Pre-defined template string. This provides the provider defaults, which can be overridden with the other IdP options. Choices: ["google","github","microsoft","okta","keycloak"] | no
organization \| ipaidporg | Organization ID string or Realm name for IdP provider templates. | no
base_url \| ipaidpbaseurl | Base URL string for IdP provider templates. | no
rename \| new_name | New name for the Identity Provider server object. Only with `state: renamed`. | no
delete_continue \| continue | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `renamed`, default: `present`. | no
Authors
=======
Thomas Woerner

View File

@@ -37,7 +37,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

153
README-idview.md Normal file
View File

@@ -0,0 +1,153 @@
Idview module
============
Description
-----------
The idview module allows to ensure presence and absence of idviews and idview host members.
Use Cases
---------
With ID views it is possible to override user or group attributes for users stored in the LDAP server. For example the login name, home directory, certificate for authentication or SSH keys. An ID view is client-side and specifies new values for user or group attributes and also the client host or hosts on which the values apply.
The ID view and the applied hosts are managed with idview, the user attributes are managed with idoverrideuser and the group attributes with idoverridegroup.
Features
--------
* Idview management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidview module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure idview "test_idview" is present:
```yaml
---
- name: Playbook to manage IPA idview.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
```
Example playbook to make sure idview "test_idview" member host "testhost.example.com" is present:
```yaml
---
- name: Playbook to manage IPA idview host member.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
```
Example playbook to make sure idview "test_idview" member host "testhost.example.com" is absent:
```yaml
---
- name: Playbook to manage IPA idview host member.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
state: absent
```
Example playbook to make sure idview "test_idview" is present with domain_resolution_order for "ad.example.com:ipa.example.com":
```yaml
---
- name: Playbook to manage IPA idview host member.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
domain_resolution_order: "ad.example.com:ipa.example.com"
```
Example playbook to make sure idview "test_idview" is absent:
```yaml
---
- name: Playbook to manage IPA idview.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
`name` \| `cn` | The list of idview name strings. | yes
`description` \| `desc` | The description string of the idview. | no
`domain_resolution_order` \| `ipadomainresolutionorder` | Colon-separated list of domains used for short name qualification. | no
`host` \| `hosts` | List of hosts to apply the ID View to. A host can only be applied to a single idview at any time. Applying a host that is already applied to a different idview will change the idview the host is applied to to the new one. | no
`rename` \| `new_name` | Rename the ID view object to the new name string. Only usable with `state: renamed`. | no
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`action` | Work on idview or member level. It can be on of `member` or `idview` and defaults to `idview`. | no
`state` | The state to ensure. It can be one of `present`, `absent` and `renamed`, default: `present`. | no
Authors
=======
Thomas Woerner

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -25,7 +25,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -23,7 +23,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -25,7 +25,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FReeIPA version (see above)

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -22,7 +22,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -21,7 +21,7 @@ Requirements
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -24,7 +24,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -30,7 +30,11 @@ Features
* Modules for hbacsvcgroup management
* Modules for host management
* Modules for hostgroup management
* Modules for idoverridegroup management
* Modules for idoverrideuser management
* Modules for idp management
* Modules for idrange management
* Modules for idview management
* Modules for location management
* Modules for netgroup management
* Modules for permission management
@@ -69,7 +73,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+ (ansible-freeipa is an Ansible Collection)
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
@@ -129,18 +133,8 @@ This command will get the whole collection from galaxy:
ansible-galaxy collection install freeipa.ansible_freeipa
```
Installing collections using the ansible-galaxy command is only supported with ansible 2.9+.
The mazer tool can be used for to install the collection for ansible 2.8:
```bash
mazer install freeipa.ansible_freeipa
```
Ansible galaxy does not support the use of dash ('-') in a name and is automatically replacing this with an underscore ('\_'). Therefore the name is `ansible_freeipa`. The ansible_freeipa collection will be placed in the directory `~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa` where it will be automatically be found for this user.
The needed adaptions of collection prefixes for `modules` and `module_utils` will be done with ansible-freeipa release `0.1.6` for galaxy.
Ansible inventory file
----------------------
@@ -450,7 +444,11 @@ Modules in plugin/modules
* [ipahbacsvcgroup](README-hbacsvcgroup.md)
* [ipahost](README-host.md)
* [ipahostgroup](README-hostgroup.md)
* [idoverridegroup](README-idoverridegroup.md)
* [idoverrideuser](README-idoverrideuser.md)
* [idp](README-idp.md)
* [idrange](README-idrange.md)
* [idview](README-idview.md)
* [ipalocation](README-location.md)
* [ipanetgroup](README-netgroup.md)
* [ipapermission](README-permission.md)

View File

@@ -1,2 +1,2 @@
---
requires_ansible: ">=2.9"
requires_ansible: ">=2.13"

View File

@@ -0,0 +1,13 @@
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: no
tasks:
- name: Ensure idoverridegroup test_group is absent in idview test_idview.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
continue: true
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: no
tasks:
- name: Ensure idoverridegroup test_group is present in idview test_idview.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group

View File

@@ -0,0 +1,13 @@
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is absent in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
continue: true
state: absent

View File

@@ -0,0 +1,15 @@
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user certificate member is absent in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
action: member
state: absent

View File

@@ -0,0 +1,14 @@
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user certificate member is present in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
action: member

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview.
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user

View File

@@ -0,0 +1,11 @@
---
- name: Idp absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure github idp my-github-idp is absent
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-github-idp
state: absent

View File

@@ -0,0 +1,12 @@
---
- name: Idp present example
hosts: ipaserver
become: no
tasks:
- name: Ensure github idp my-github-idp is present
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-github-idp
provider: github
client_id: my-github-client-id

View File

@@ -0,0 +1,11 @@
---
- name: Idview absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure idview test_idview is absent
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
state: absent

View File

@@ -0,0 +1,12 @@
---
- name: Idview host member applied example
hosts: ipaserver
become: no
tasks:
- name: Ensure host testhost.example.com is applied to idview test_idview
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member

View File

@@ -0,0 +1,13 @@
---
- name: Idview host member unapplied example
hosts: ipaserver
become: no
tasks:
- name: Ensure host testhost.example.com is not applied to idview test_idview
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
state: absent

View File

@@ -0,0 +1,10 @@
---
- name: Idview present example
hosts: ipaserver
become: no
tasks:
- name: Ensure idview test_idview is present
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview

View File

@@ -30,7 +30,7 @@ __all__ = ["gssapi", "netaddr", "api", "ipalib_errors", "Env",
"kinit_password", "kinit_keytab", "run", "DN", "VERSION",
"paths", "tasks", "get_credentials_if_valid", "Encoding",
"DNSName", "getargspec", "certificate_loader",
"write_certificate_list", "boolean"]
"write_certificate_list", "boolean", "template_str"]
import os
# ansible-freeipa requires locale to be C, IPA requires utf-8.
@@ -90,6 +90,7 @@ try:
except ImportError:
from ipapython.ipautil import kinit_password, kinit_keytab
from ipapython.ipautil import run
from ipapython.ipautil import template_str
from ipapython.dn import DN
from ipapython.version import VERSION
from ipaplatform.paths import paths
@@ -226,7 +227,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
"""Destroy temporary ticket and remove temporary ccache."""
if ccache_name is not None:
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
del os.environ['KRB5CCNAME']
os.environ.pop('KRB5CCNAME', None)
if ccache_dir is not None:
shutil.rmtree(ccache_dir, ignore_errors=True)

View File

@@ -121,8 +121,7 @@ class AutomountKey(IPAAnsibleModule):
resp = self.ipa_command("automountkey_show", location, args)
except ipalib_errors.NotFound:
return None
else:
return resp.get("result")
return resp.get("result")
def check_ipa_params(self):
invalid = []

View File

@@ -92,8 +92,7 @@ class AutomountLocation(IPAAnsibleModule):
)
except ipalib_errors.NotFound:
return None
else:
return response.get("result", None)
return response.get("result", None)
def check_ipa_params(self):
if len(self.params_get("name")) == 0:

View File

@@ -126,8 +126,7 @@ class AutomountMap(IPAAnsibleModule):
)
except Exception: # pylint: disable=broad-except
return None
else:
return response["result"]
return response["result"]
def get_indirect_map_keys(self, location, name):
"""Check if 'name' is an indirect map for 'parentmap'."""

View File

@@ -358,8 +358,7 @@ def get_netbios_name(module):
_result = module.ipa_command_no_name("trustconfig_show", {"all": True})
except Exception: # pylint: disable=broad-except
return None
else:
return _result["result"]["ipantflatname"][0]
return _result["result"]["ipantflatname"][0]
def is_enable_sid(module):
@@ -477,7 +476,7 @@ def main():
params = {}
for x in field_map:
val = ansible_module.params_get(
x, allow_empty_string=(x in allow_empty_string))
x, allow_empty_string=x in allow_empty_string)
if val is not None:
params[field_map.get(x, x)] = val
@@ -620,7 +619,7 @@ def main():
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
exit_args[k] = (str(value[0]).upper() == "TRUE")
exit_args[k] = str(value[0]).upper() == "TRUE"
else:
if arg_type not in type_map:
raise ValueError(

View File

@@ -134,8 +134,7 @@ def find_delegation(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if delegation name is not found.
return None
else:
return _result["result"]
return _result["result"]
def gen_args(permission, attribute, membergroup, group):

View File

@@ -258,7 +258,7 @@ def main():
invalid = [
"forwarders", "forwardpolicy", "skip_overlap_check", "permission"
]
wants_enable = (state == "enabled")
wants_enable = state == "enabled"
if operation == "del":
invalid = [

View File

@@ -1453,7 +1453,7 @@ def define_commands_for_present_state(module, zone_name, entry, res_find):
else:
# Create reverse records for existing records
for ipv in ['a', 'aaaa']:
record = ('%srecord' % ipv)
record = '%srecord' % ipv
if record in args and ('%s_extra_create_reverse' % ipv) in args:
cmds = create_reverse_ip_record(
module, zone_name, name, args[record])

View File

@@ -186,7 +186,17 @@ def find_hbacrule(module, name):
module.fail_json(
msg="There is more than one hbacrule '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
res = _result["result"][0]
# hbacsvcgroup names are converted to lower case while creation with
# hbacsvcgroup_add.
# The hbacsvcgroup for sudo is builtin with the name "Sudo" though.
# This breaks the lower case comparison. Therefore all
# memberservice_hbacsvcgroup items are converted to lower case if
# "Sudo" is in the list.
_member = "memberservice_hbacsvcgroup"
if _member in res and "Sudo" in res[_member]:
res[_member] = [item.lower() for item in res[_member]]
return res
return None

View File

@@ -146,21 +146,6 @@ def gen_member_args(hbacsvc):
return _args
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
@@ -303,7 +288,8 @@ def main():
}])
# Execute commands
changed = ansible_module.execute_ipa_commands(commands, result_handler)
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done

View File

@@ -0,0 +1,354 @@
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, exither version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
DOCUMENTATION = """
---
module: ipaidoverridegroup
short_description: Manage FreeIPA idoverridegroup
description: Manage FreeIPA idoverridegroups
extends_documentation_fragment:
- ipamodule_base_docs
options:
idview:
description: The idoverridegroup idview string.
type: str
required: true
aliases: ["idviewcn"]
anchor:
description: The list of anchors to override
type: list
elements: str
required: true
aliases: ["ipaanchoruuid"]
description:
description: Description
type: str
required: False
aliases: ["desc"]
name:
description: Group name
type: str
required: False
aliases: ["group_name", "cn"]
gid:
description: Group ID Number (int or "")
type: str
required: False
aliases: ["gidnumber"]
fallback_to_ldap:
description: |
Allow falling back to AD DC LDAP when resolving AD trusted objects.
For two-way trusts only.
required: False
type: bool
delete_continue:
description: |
Continuous mode. Don't stop on errors.
Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure test group test_group is present in idview test_idview
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
# Ensure test group test_group is present in idview test_idview with
# description
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: "test_group description"
# Ensure test group test_group is present in idview test_idview without
# description
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: ""
# Ensure test group test_group is present in idview test_idview with internal
# name test_123_group
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: test_123_group
# Ensure test group test_group is present in idview test_idview without
# internal name
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: ""
# Ensure test group test_group is present in idview test_idview with gid 20001
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: 20001
# Ensure test group test_group is present in idview test_idview without gid
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: ""
# Ensure test group test_group is absent in idview test_idview
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
continue: true
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_idoverridegroup(module, idview, anchor):
"""Find if a idoverridegroup with the given name already exist."""
try:
_result = module.ipa_command("idoverridegroup_show", idview,
{"ipaanchoruuid": anchor,
"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idoverridegroup anchor is not found.
return None
return _result["result"]
def gen_args(anchor, description, name, gid):
# fallback_to_ldap is only a runtime tuning parameter
_args = {}
if anchor is not None:
_args["ipaanchoruuid"] = anchor
if description is not None:
_args["description"] = description
if name is not None:
_args["cn"] = name
if gid is not None:
_args["gidnumber"] = gid
return _args
def gen_args_runtime(fallback_to_ldap):
_args = {}
if fallback_to_ldap is not None:
_args["fallback_to_ldap"] = fallback_to_ldap
return _args
def merge_dicts(dict1, dict2):
ret = dict1.copy()
ret.update(dict2)
return ret
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
idview=dict(type="str", required=True, aliases=["idviewcn"]),
anchor=dict(type="list", elements="str", required=True,
aliases=["ipaanchoruuid"]),
# present
description=dict(type="str", required=False, aliases=["desc"]),
name=dict(type="str", required=False,
aliases=["group_name", "cn"]),
gid=dict(type="str", required=False, aliases=["gidnumber"]),
# runtime flags
fallback_to_ldap=dict(type="bool", required=False),
# absent
delete_continue=dict(type="bool", required=False,
aliases=['continue'], default=None),
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
idview = ansible_module.params_get("idview")
anchors = ansible_module.params_get("anchor")
# present
description = ansible_module.params_get("description")
name = ansible_module.params_get("name")
gid = ansible_module.params_get("gid")
# runtime flags
fallback_to_ldap = ansible_module.params_get("fallback_to_ldap")
# absent
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(anchors) != 1:
ansible_module.fail_json(
msg="Only one idoverridegroup can be added at a time.")
invalid = ["delete_continue"]
if state == "absent":
if len(anchors) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "name", "gid"]
ansible_module.params_fail_used_invalid(invalid, state)
# Ensure parameter values are valid and have proper type.
def int_or_empty_param(value, param):
if value is not None and value != "":
try:
value = int(value)
except ValueError:
ansible_module.fail_json(
msg="Invalid value '%s' for argument '%s'" % (value, param)
)
return value
gid = int_or_empty_param(gid, "gid")
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
runtime_args = gen_args_runtime(fallback_to_ldap)
commands = []
for anchor in anchors:
# Make sure idoverridegroup exists
res_find = find_idoverridegroup(ansible_module, idview, anchor)
# Create command
if state == "present":
# Generate args
args = gen_args(anchor, description, name, gid)
# fallback_to_ldap is only a runtime tuning parameter
all_args = merge_dicts(args, runtime_args)
# Found the idoverridegroup
if res_find is not None:
# For idempotency: Remove empty sshpubkey list if
# there are no sshpubkey in the found entry.
if "ipasshpubkey" in args and \
len(args["ipasshpubkey"]) < 1 and \
"ipasshpubkey" not in res_find:
del args["ipasshpubkey"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([idview, "idoverridegroup_mod",
all_args])
else:
commands.append([idview, "idoverridegroup_add",
all_args])
elif state == "absent":
if res_find is not None:
commands.append(
[idview, "idoverridegroup_del",
merge_dicts(
{
"ipaanchoruuid": anchor,
"continue": delete_continue or False
},
runtime_args
)]
)
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,631 @@
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
DOCUMENTATION = """
---
module: ipaidoverrideuser
short_description: Manage FreeIPA idoverrideuser
description: Manage FreeIPA idoverrideuser and idoverrideuser members
extends_documentation_fragment:
- ipamodule_base_docs
options:
idview:
description: The idoverrideuser idview string.
type: str
required: true
aliases: ["idviewcn"]
anchor:
description: The list of anchors to override
type: list
elements: str
required: true
aliases: ["ipaanchoruuid"]
description:
description: Description
type: str
required: False
aliases: ["desc"]
name:
description: The user (internally uid)
type: str
required: False
aliases: ["login"]
uid:
description: User ID Number (int or "")
type: str
required: False
aliases: ["uidnumber"]
gecos:
description: GECOS
required: False
type: str
gidnumber:
description: Group ID Number (int or "")
required: False
type: str
homedir:
description: Home directory
type: str
required: False
aliases: ["homedirectory"]
shell:
description: Login shell
type: str
required: False
aliases: ["loginshell"]
sshpubkey:
description: List of SSH public keys
type: list
element: str
required: False
aliases: ["ipasshpubkey"]
certificate:
description: List of Base-64 encoded user certificates
type: list
elements: str
required: False
aliases: ["usercertificate"]
fallback_to_ldap:
description: |
Allow falling back to AD DC LDAP when resolving AD trusted objects.
For two-way trusts only.
required: False
type: bool
delete_continue:
description: |
Continuous mode. Don't stop on errors.
Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
nomembers:
description: |
Suppress processing of membership attributes.
Valid only if `state` is `absent`.
type: str
required: False
aliases: ["no_members"]
action:
description: Work on idoverrideuser or member level.
choices: ["idoverrideuser", "member"]
default: idoverrideuser
type: str
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure test user test_user is present in idview test_idview
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
# Ensure test user test_user is present in idview test_idview with description
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: "test_user description"
# Ensure test user test_user is present in idview test_idview without
# description
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: ""
# Ensure test user test_user is present in idview test_idview with internal
# name test_123_user
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: test_123_user
# Ensure test user test_user is present in idview test_idview without internal
# name
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: ""
# Ensure test user test_user is present in idview test_idview with uid 20001
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: 20001
# Ensure test user test_user is present in idview test_idview without uid
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: ""
# Ensure test user test_user is present in idview test_idview with gecos
# "Gecos Test"
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: Gecos Test
# Ensure test user test_user is present in idview test_idview without gecos
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: ""
# Ensure test user test_user is present in idview test_idview with gidnumber
# 20001
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: 20001
# Ensure test user test_user is present in idview test_idview without
# gidnumber
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: ""
# Ensure test user test_user is present in idview test_idview with homedir
# /Users
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: /Users
# Ensure test user test_user is present in idview test_idview without homedir
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: ""
# Ensure test user test_user is present in idview test_idview with shell
# /bin/someshell
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: /bin/someshell
# Ensure test user test_user is present in idview test_idview without shell
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: ""
# Ensure test user test_user is present in idview test_idview with sshpubkey
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey:
- ssh-rsa AAAAB3NzaC1yc2EAAADAQABAAABgQCqmVDpEX5gnSjKuv97Ay ...
# Ensure test user test_user is present in idview test_idview without
# sshpubkey
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey: []
# Ensure test user test_user is present in idview test_idview with 1
# certificate
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
# Ensure test user test_user is present in idview test_idview with 3
# certificate members
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
# Ensure test user test_user is present in idview test_idview without
# 2 certificate members
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
# Ensure test user test_user is present in idview test_idview without
# certificates
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate: []
# Ensure test user test_user is absent in idview test_idview
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
continue: true
state: absent
"""
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
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_idoverrideuser(module, idview, anchor):
"""Find if a idoverrideuser with the given name already exist."""
try:
_result = module.ipa_command("idoverrideuser_show", idview,
{"ipaanchoruuid": anchor,
"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idoverrideuser anchor is not found.
return None
_res = _result["result"]
certs = _res.get("usercertificate")
if certs is not None:
_res["usercertificate"] = [encode_certificate(cert) for cert in certs]
return _res
def gen_args(anchor, description, name, uid, gecos, gidnumber, homedir, shell,
sshpubkey):
# fallback_to_ldap and nomembers are only runtime tuning parameters
_args = {}
if anchor is not None:
_args["ipaanchoruuid"] = anchor
if description is not None:
_args["description"] = description
if name is not None:
_args["uid"] = name
if uid is not None:
_args["uidnumber"] = uid
if gecos is not None:
_args["gecos"] = gecos
if gidnumber is not None:
_args["gidnumber"] = gidnumber
if homedir is not None:
_args["homedirectory"] = homedir
if shell is not None:
_args["loginshell"] = shell
if sshpubkey is not None:
_args["ipasshpubkey"] = sshpubkey
return _args
def gen_args_runtime(fallback_to_ldap, nomembers):
_args = {}
if fallback_to_ldap is not None:
_args["fallback_to_ldap"] = fallback_to_ldap
if nomembers is not None:
_args["no_members"] = nomembers
return _args
def gen_member_args(certificate):
_args = {}
if certificate is not None:
_args["usercertificate"] = certificate
return _args
def merge_dicts(dict1, dict2):
ret = dict1.copy()
ret.update(dict2)
return ret
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
idview=dict(type="str", required=True, aliases=["idviewcn"]),
anchor=dict(type="list", elements="str", required=True,
aliases=["ipaanchoruuid"]),
# present
description=dict(type="str", required=False, aliases=["desc"]),
name=dict(type="str", required=False, aliases=["login"]),
uid=dict(type="str", required=False, aliases=["uidnumber"]),
gecos=dict(type="str", required=False),
gidnumber=dict(type="str", required=False),
homedir=dict(type="str", required=False,
aliases=["homedirectory"]),
shell=dict(type="str", required=False, aliases=["loginshell"]),
sshpubkey=dict(type="list", elements="str", required=False,
aliases=["ipasshpubkey"]),
certificate=dict(type="list", elements="str", required=False,
aliases=["usercertificate"]),
fallback_to_ldap=dict(type="bool", required=False),
nomembers=dict(type="bool", required=False,
aliases=["no_members"]),
# absent
delete_continue=dict(type="bool", required=False,
aliases=['continue'], default=None),
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
# action
action=dict(type="str", default="idoverrideuser",
choices=["member", "idoverrideuser"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
idview = ansible_module.params_get("idview")
anchors = ansible_module.params_get("anchor")
# present
description = ansible_module.params_get("description")
name = ansible_module.params_get("name")
uid = ansible_module.params_get("uid")
gecos = ansible_module.params_get("gecos")
gidnumber = ansible_module.params_get("gidnumber")
homedir = ansible_module.params_get("homedir")
shell = ansible_module.params_get("shell")
sshpubkey = ansible_module.params_get("sshpubkey")
certificate = ansible_module.params_get("certificate")
fallback_to_ldap = ansible_module.params_get("fallback_to_ldap")
nomembers = ansible_module.params_get("nomembers")
action = ansible_module.params_get("action")
# absent
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(anchors) != 1:
ansible_module.fail_json(
msg="Only one idoverrideuser can be added at a time.")
invalid = ["delete_continue"]
if action == "member":
invalid += ["description", "name", "uid", "gecos", "gidnumber",
"homedir", "shell", "sshpubkey"]
if state == "absent":
if len(anchors) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "name", "uid", "gecos", "gidnumber",
"homedir", "shell", "sshpubkey", "nomembers"]
if action == "idoverrideuser":
invalid += ["certificate"]
ansible_module.params_fail_used_invalid(invalid, state, action)
# Ensure parameter values are valid and have proper type.
def int_or_empty_param(value, param):
if value is not None and value != "":
try:
value = int(value)
except ValueError:
ansible_module.fail_json(
msg="Invalid value '%s' for argument '%s'" % (value, param)
)
return value
uid = int_or_empty_param(uid, "uid")
gidnumber = int_or_empty_param(gidnumber, "gidnumber")
if certificate is not None:
certificate = [cert.strip() for cert in certificate]
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
runtime_args = gen_args_runtime(fallback_to_ldap, nomembers)
commands = []
for anchor in anchors:
# Make sure idoverrideuser exists
res_find = find_idoverrideuser(ansible_module, idview, anchor)
# add/del lists
certificate_add, certificate_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(anchor, description, name, uid, gecos,
gidnumber, homedir, shell, sshpubkey)
# fallback_to_ldap and nomembers are only runtime tuning
# parameters
all_args = merge_dicts(args, runtime_args)
if action == "idoverrideuser":
# Found the idoverrideuser
if res_find is not None:
# For idempotency: Remove empty sshpubkey list if
# there are no sshpubkey in the found entry.
if "ipasshpubkey" in args and \
len(args["ipasshpubkey"]) < 1 and \
"ipasshpubkey" not in res_find:
del args["ipasshpubkey"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([idview, "idoverrideuser_mod",
all_args])
else:
commands.append([idview, "idoverrideuser_add",
all_args])
res_find = {}
member_args = gen_member_args(certificate)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
certificate_add, certificate_del = gen_add_del_lists(
certificate, res_find.get("usercertificate"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idoverrideuser '%s' in idview '%s'" %
(anchor, idview))
# Reduce add lists for certificate
# to new entries only that are not in res_find.
if certificate is not None:
certificate_add = gen_add_list(
certificate, res_find.get("usercertificate"))
elif state == "absent":
if action == "idoverrideuser":
if res_find is not None:
commands.append(
[idview, "idoverrideuser_del",
merge_dicts(
{
"ipaanchoruuid": anchor,
"continue": delete_continue or False
},
runtime_args
)]
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idoverrideuser '%s' in idview '%s'" %
(anchor, idview))
# Reduce del lists of member_host and member_hostgroup,
# to the entries only that are in res_find.
if certificate is not None:
certificate_del = gen_intersection_list(
certificate, res_find.get("usercertificate"))
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Member management
# Add members
if certificate_add:
commands.append([idview, "idoverrideuser_add_cert",
merge_dicts(
{
"ipaanchoruuid": anchor,
"usercertificate": certificate_add
},
runtime_args
)])
# Remove members
if certificate_del:
commands.append([idview, "idoverrideuser_remove_cert",
merge_dicts(
{
"ipaanchoruuid": anchor,
"usercertificate": certificate_del
},
runtime_args
)])
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

544
plugins/modules/ipaidp.py Normal file
View File

@@ -0,0 +1,544 @@
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaidp
short_description: Manage FreeIPA idp
description: Manage FreeIPA idp
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of idp name strings.
required: true
type: list
elements: str
aliases: ["cn"]
auth_uri:
description: OAuth 2.0 authorization endpoint
required: false
type: str
aliases: ["ipaidpauthendpoint"]
dev_auth_uri:
description: Device authorization endpoint
required: false
type: str
aliases: ["ipaidpdevauthendpoint"]
token_uri:
description: Token endpoint
required: false
type: str
aliases: ["ipaidptokenendpoint"]
userinfo_uri:
description: User information endpoint
required: false
type: str
aliases: ["ipaidpuserinfoendpoint"]
keys_uri:
description: JWKS endpoint
required: false
type: str
aliases: ["ipaidpkeysendpoint"]
issuer_url:
description: The Identity Provider OIDC URL
required: false
type: str
aliases: ["ipaidpissuerurl"]
client_id:
description: OAuth 2.0 client identifier
required: false
type: str
aliases: ["ipaidpclientid"]
secret:
description: OAuth 2.0 client secret
required: false
type: str
no_log: true
aliases: ["ipaidpclientsecret"]
scope:
description: OAuth 2.0 scope. Multiple scopes separated by space
required: false
type: str
aliases: ["ipaidpscope"]
idp_user_id:
description: Attribute for user identity in OAuth 2.0 userinfo
required: false
type: str
aliases: ["ipaidpsub"]
provider:
description: |
Pre-defined template string. This provides the provider defaults, which
can be overridden with the other IdP options.
required: false
type: str
choices: ["google","github","microsoft","okta","keycloak"]
aliases: ["ipaidpprovider"]
organization:
description: Organization ID or Realm name for IdP provider templates
required: false
type: str
aliases: ["ipaidporg"]
base_url:
description: Base URL for IdP provider templates
required: false
type: str
aliases: ["ipaidpbaseurl"]
rename:
description: |
New name the Identity Provider server object. Only with state: renamed.
required: false
type: str
aliases: ["new_name"]
delete_continue:
description:
Continuous mode. Don't stop on errors. Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure keycloak idp my-keycloak-idp is present
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
provider: keycloak
organization: main
base_url: keycloak.idm.example.com:8443/auth
client_id: my-client-id
# Ensure google idp my-google-idp is present
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
auth_uri: https://accounts.google.com/o/oauth2/auth
dev_auth_uri: https://oauth2.googleapis.com/device/code
token_uri: https://oauth2.googleapis.com/token
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
client_id: my-client-id
scope: "openid email"
idp_user_id: email
# Ensure google idp my-google-idp is present without using provider
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
provider: google
client_id: my-google-client-id
# Ensure keycloak idp my-keycloak-idp is absent
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
delete_continue: true
state: absent
# Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
- ipaidp:
ipaadmin_password: SomeADMINpassword
name:
- my-keycloak-idp
- my-github-idp
- my-google-idp
delete_continue: true
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, template_str
from ansible.module_utils import six
from copy import deepcopy
import string
from itertools import chain
if six.PY3:
unicode = str
# Copy from FreeIPA ipaserver/plugins/idp.py
idp_providers = {
'google': {
'ipaidpauthendpoint':
'https://accounts.google.com/o/oauth2/auth',
'ipaidpdevauthendpoint':
'https://oauth2.googleapis.com/device/code',
'ipaidptokenendpoint':
'https://oauth2.googleapis.com/token',
'ipaidpuserinfoendpoint':
'https://openidconnect.googleapis.com/v1/userinfo',
'ipaidpkeysendpoint':
'https://www.googleapis.com/oauth2/v3/certs',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email'},
'github': {
'ipaidpauthendpoint':
'https://github.com/login/oauth/authorize',
'ipaidpdevauthendpoint':
'https://github.com/login/device/code',
'ipaidptokenendpoint':
'https://github.com/login/oauth/access_token',
'ipaidpuserinfoendpoint':
'https://api.github.com/user',
'ipaidpscope': 'user',
'ipaidpsub': 'login'},
'microsoft': {
'ipaidpauthendpoint':
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
'authorize',
'ipaidpdevauthendpoint':
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
'devicecode',
'ipaidptokenendpoint':
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
'token',
'ipaidpuserinfoendpoint':
'https://graph.microsoft.com/oidc/userinfo',
'ipaidpkeysendpoint':
'https://login.microsoftonline.com/common/discovery/v2.0/keys',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email',
},
'okta': {
'ipaidpauthendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/authorize',
'ipaidpdevauthendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/device/authorize',
'ipaidptokenendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/token',
'ipaidpuserinfoendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/userinfo',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email'},
'keycloak': {
'ipaidpauthendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/auth',
'ipaidpdevauthendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/auth/device',
'ipaidptokenendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/token',
'ipaidpuserinfoendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/userinfo',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email'},
}
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
# An exception is raised if idp name is not found.
return None
return _result["result"]
def gen_args(auth_uri, dev_auth_uri, token_uri, userinfo_uri, keys_uri,
issuer_url, client_id, secret, scope, idp_user_id, organization,
base_url):
_args = {}
if auth_uri is not None:
_args["ipaidpauthendpoint"] = auth_uri
if dev_auth_uri is not None:
_args["ipaidpdevauthendpoint"] = dev_auth_uri
if token_uri is not None:
_args["ipaidptokenendpoint"] = token_uri
if userinfo_uri is not None:
_args["ipaidpuserinfoendpoint"] = userinfo_uri
if keys_uri is not None:
_args["ipaidpkeysendpoint"] = keys_uri
if issuer_url is not None:
_args["ipaidpissuerurl"] = issuer_url
if client_id is not None:
_args["ipaidpclientid"] = client_id
if secret is not None:
_args["ipaidpclientsecret"] = secret
if scope is not None:
_args["ipaidpscope"] = scope
if idp_user_id is not None:
_args["ipaidpsub"] = idp_user_id
if organization is not None:
_args["ipaidporg"] = organization
if base_url is not None:
_args["ipaidpbaseurl"] = base_url
return _args
# Copied and adapted from FreeIPA ipaserver/plugins/idp.py
def convert_provider_to_endpoints(module, _args, provider):
"""Convert provider option to auth-uri and token-uri,.."""
if provider not in idp_providers:
module.fail_json(msg="Provider '%s' is unknown" % provider)
# For each string in the template check if a variable
# is required, it is provided as an option
points = deepcopy(idp_providers[provider])
_r = string.Template.pattern
for (_k, _v) in points.items():
# build list of variables to be replaced
subs = list(chain.from_iterable(
(filter(None, _s) for _s in _r.findall(_v))))
if subs:
for _s in subs:
if _s not in _args:
module.fail_json(msg="Parameter '%s' is missing" % _s)
points[_k] = template_str(_v, _args)
elif _k in _args:
points[_k] = _args[_k]
_args.update(points)
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", required=True,
aliases=["cn"]),
# present
auth_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpauthendpoint"]),
dev_auth_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpdevauthendpoint"]),
token_uri=dict(required=False, type="str", default=None,
aliases=["ipaidptokenendpoint"]),
userinfo_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpuserinfoendpoint"]),
keys_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpkeysendpoint"]),
issuer_url=dict(required=False, type="str", default=None,
aliases=["ipaidpissuerurl"]),
client_id=dict(required=False, type="str", default=None,
aliases=["ipaidpclientid"]),
secret=dict(required=False, type="str", default=None,
aliases=["ipaidpclientsecret"], no_log=True),
scope=dict(required=False, type="str", default=None,
aliases=["ipaidpscope"]),
idp_user_id=dict(required=False, type="str", default=None,
aliases=["ipaidpsub"]),
provider=dict(required=False, type="str", default=None,
aliases=["ipaidpprovider"],
choices=["google", "github", "microsoft", "okta",
"keycloak"]),
organization=dict(required=False, type="str", default=None,
aliases=["ipaidporg"]),
base_url=dict(required=False, type="str", default=None,
aliases=["ipaidpbaseurl"]),
rename=dict(required=False, type="str", default=None,
aliases=["new_name"]),
delete_continue=dict(required=False, type="bool", default=None,
aliases=['continue']),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
# mutually_exclusive=[],
# required_one_of=[]
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
auth_uri = ansible_module.params_get("auth_uri")
dev_auth_uri = ansible_module.params_get("dev_auth_uri")
token_uri = ansible_module.params_get("token_uri")
userinfo_uri = ansible_module.params_get("userinfo_uri")
keys_uri = ansible_module.params_get("keys_uri")
issuer_url = ansible_module.params_get("issuer_url")
client_id = ansible_module.params_get("client_id")
secret = ansible_module.params_get("secret")
scope = ansible_module.params_get("scope")
idp_user_id = ansible_module.params_get("idp_user_id")
provider = ansible_module.params_get("provider")
organization = ansible_module.params_get("organization")
base_url = ansible_module.params_get("base_url")
rename = ansible_module.params_get("rename")
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idp can be added at a time.")
if provider:
if any([auth_uri, dev_auth_uri, token_uri, userinfo_uri,
keys_uri]):
ansible_module.fail_json(
msg="Cannot specify both individual endpoints and IdP "
"provider")
if provider not in idp_providers:
ansible_module.fail_json(
msg="Provider '%s' is unknown" % provider)
else:
if not auth_uri:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "auth_uri")
if not dev_auth_uri:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "dev_auth_uri")
if not token_uri:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "token_uri")
if not userinfo_uri:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "userinfo_uri")
invalid = ["rename", "delete_continue"]
else:
# state renamed and absent
invalid = ["auth_uri", "dev_auth_uri", "token_uri", "userinfo_uri",
"keys_uri", "issuer_url", "client_id", "secret", "scope",
"idp_user_id", "provider", "organization", "base_url"]
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one permission can be renamed at a time.")
invalid += ["delete_continue"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid += ["rename"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
if not ansible_module.ipa_command_exists("idp_add"):
ansible_module.fail_json(
msg="Managing idp is not supported by your IPA version")
commands = []
for name in names:
# Make sure idp exists
res_find = find_idp(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(auth_uri, dev_auth_uri, token_uri,
userinfo_uri, keys_uri, issuer_url, client_id,
secret, scope, idp_user_id, organization,
base_url)
if provider is not None:
convert_provider_to_endpoints(ansible_module, args,
provider)
# Found the idp
if res_find is not None:
# The parameters ipaidpprovider, ipaidporg and
# ipaidpbaseurl are only available for idp-add to create
# then endpoints using provider, Therefore we have to
# remove them from args.
for arg in ["ipaidpprovider", "ipaidporg",
"ipaidpbaseurl"]:
if arg in args:
del args[arg]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "idp_mod", args])
else:
commands.append([name, "idp_add", args])
elif state == "absent":
if res_find is not None:
_args = {}
if delete_continue is not None:
_args = {"continue": delete_continue}
commands.append([name, "idp_del", _args])
elif state == "renamed":
if not rename:
ansible_module.fail_json(msg="No rename value given.")
if res_find is None:
ansible_module.fail_json(
msg="No idp found to be renamed: '%s'" % (name))
if name != rename:
commands.append(
[name, "idp_mod", {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -157,8 +157,7 @@ def find_idrange(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if idrange name is not found.
return None
else:
return _result["result"]
return _result["result"]
def gen_args(

View File

@@ -0,0 +1,362 @@
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaidview
short_description: Manage FreeIPA idview
description: Manage FreeIPA idview and idview host members
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of idview name strings.
required: true
type: list
elements: str
aliases: ["cn"]
description:
description: Description
required: False
type: str
aliases: ["desc"]
domain_resolution_order:
description: |
Colon-separated list of domains used for short name qualification
required: False
type: str
aliases: ["ipadomainresolutionorder"]
host:
description: Hosts to apply the ID View to
required: False
type: list
elements: str
aliases: ["hosts"]
rename:
description: Rename the ID view object
required: False
type: str
aliases: ["new_name"]
delete_continue:
description: |
Continuous mode. Don't stop on errors.
Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
action:
description: Work on idview or member level.
choices: ["idview", "member"]
default: idview
type: str
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure idview test_idview is present
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
# name: Ensure host testhost.example.com is applied to idview test_idview
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
# Ensure host testhost.example.com is not applied to idview test_idview
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
state: absent
# Ensure idview "test_idview" is present with domain_resolution_order for
# "ad.example.com:ipa.example.com"
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
domain_resolution_order: "ad.example.com:ipa.example.com"
# Ensure idview test_idview is absent
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, ipalib_errors
from ansible.module_utils import six
if six.PY3:
unicode = str
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
# An exception is raised if idview name is not found.
return None
return _result["result"]
def valid_host(module, name):
try:
module.ipa_command("host_show", name, {})
except ipalib_errors.NotFound:
return False
return True
def gen_args(description, domain_resolution_order):
_args = {}
if description is not None:
_args["description"] = description
if domain_resolution_order is not None:
_args["ipadomainresolutionorder"] = domain_resolution_order
return _args
def gen_member_args(host):
_args = {}
if host is not None:
_args["host"] = host
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", required=True,
aliases=["cn"]),
# present
description=dict(type="str", required=False, aliases=["desc"]),
domain_resolution_order=dict(type="str", required=False,
aliases=["ipadomainresolutionorder"]),
host=dict(type="list", elements="str", required=False,
aliases=["hosts"], default=None),
rename=dict(type="str", required=False, aliases=["new_name"]),
delete_continue=dict(type="bool", required=False,
aliases=['continue'], default=None),
# action
action=dict(type="str", default="idview",
choices=["member", "idview"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
domain_resolution_order = ansible_module.params_get(
"domain_resolution_order")
host = ansible_module.params_get("host")
rename = ansible_module.params_get("rename")
action = ansible_module.params_get("action")
# absent
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idview can be added at a time.")
invalid = ["delete_continue", "rename"]
if action == "member":
invalid += ["description", "domain_resolution_order"]
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idoverridegroup can be renamed at a time.")
if not rename:
ansible_module.fail_json(
msg="Rename is required for state: renamed.")
if action == "member":
ansible_module.fail_json(
msg="Action member can not be used with state: renamed.")
invalid = ["description", "domain_resolution_order", "host",
"delete_continue"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "domain_resolution_order", "rename"]
if action == "idview":
invalid += ["host"]
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure idview exists
res_find = find_idview(ansible_module, name)
# add/del lists
host_add, host_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(description, domain_resolution_order)
if action == "idview":
# Found the idview
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "idview_mod", args])
else:
commands.append([name, "idview_add", args])
res_find = {}
member_args = gen_member_args(host)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
host_add, host_del = gen_add_del_lists(
host, res_find.get("appliedtohosts"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idview '%s'" % name)
# Reduce add lists for host
# to new entries only that are not in res_find.
if host is not None:
host_add = gen_add_list(
host, res_find.get("appliedtohosts"))
elif state == "absent":
if action == "idview":
if res_find is not None:
commands.append(
[name, "idview_del",
{"continue": delete_continue or False}]
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idview '%s'" % name)
# Reduce del lists of member_host
# to the entries only that are in res_find.
if host is not None:
host_del = gen_intersection_list(
host, res_find.get("appliedtohosts"))
elif state == "renamed":
if res_find is None:
ansible_module.fail_json(msg="No idview '%s'" % name)
else:
commands.append([name, 'idview_mod', {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Member management
# Add members
if host_add:
for host in host_add:
if not valid_host(ansible_module, host):
ansible_module.fail_json("Invalid host '%s'" % host)
commands.append([name, "idview_apply", {"host": host_add}])
# Remove members
if host_del:
# idview_unapply does not have the idview name (cn) as an arg.
# It is removing the host from any idview it is applied to.
# But as we create the intersection with the list of hosts of
# the idview, we emulate the correct behaviour. But this means
# that there is no general idview_unapply like in the cli.
commands.append([None, "idview_unapply", {"host": host_del}])
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -86,8 +86,7 @@ def find_location(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if location name is not found.
return None
else:
return _result["result"]
return _result["result"]
def gen_args(description):

View File

@@ -164,8 +164,7 @@ def find_permission(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if permission name is not found.
return None
else:
return _result["result"]
return _result["result"]
def gen_args(right, attrs, bindtype, subtree,

View File

@@ -138,8 +138,7 @@ def find_privilege(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if privilege name is not found.
return None
else:
return _result["result"]
return _result["result"]
def main():

View File

@@ -143,8 +143,7 @@ def find_role(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if role name is not found.
return None
else:
return _result["result"]
return _result["result"]
def gen_args(module):

View File

@@ -123,8 +123,7 @@ def find_selfservice(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if selfservice name is not found.
return None
else:
return _result["result"]
return _result["result"]
def gen_args(permission, attribute):

View File

@@ -202,8 +202,7 @@ def find_server(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if server name is not found.
return None
else:
return _result["result"]
return _result["result"]
def server_role_status(module, name):
@@ -218,8 +217,7 @@ def server_role_status(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if server name is not found.
return None
else:
return _result["result"][0]
return _result["result"][0]
def gen_args(location, service_weight, no_members, delete_continue,

View File

@@ -414,15 +414,15 @@ def gen_args(pac_type, auth_ind, skip_host_check, force, requires_pre_auth,
if auth_ind is not None:
_args['krbprincipalauthind'] = auth_ind
if skip_host_check is not None:
_args['skip_host_check'] = (skip_host_check)
_args['skip_host_check'] = skip_host_check
if force is not None:
_args['force'] = (force)
_args['force'] = force
if requires_pre_auth is not None:
_args['ipakrbrequirespreauth'] = (requires_pre_auth)
_args['ipakrbrequirespreauth'] = requires_pre_auth
if ok_as_delegate is not None:
_args['ipakrbokasdelegate'] = (ok_as_delegate)
_args['ipakrbokasdelegate'] = ok_as_delegate
if ok_to_auth_as_delegate is not None:
_args['ipakrboktoauthasdelegate'] = (ok_to_auth_as_delegate)
_args['ipakrboktoauthasdelegate'] = ok_to_auth_as_delegate
return _args
@@ -433,9 +433,9 @@ def gen_args_smb(netbiosname, ok_as_delegate, ok_to_auth_as_delegate):
if netbiosname is not None:
_args['ipantflatname'] = netbiosname
if ok_as_delegate is not None:
_args['ipakrbokasdelegate'] = (ok_as_delegate)
_args['ipakrbokasdelegate'] = ok_as_delegate
if ok_to_auth_as_delegate is not None:
_args['ipakrboktoauthasdelegate'] = (ok_to_auth_as_delegate)
_args['ipakrboktoauthasdelegate'] = ok_to_auth_as_delegate
return _args

View File

@@ -145,8 +145,7 @@ def find_servicedelegationrule(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if servicedelegationrule name is not found.
return None
else:
return _result["result"]
return _result["result"]
def check_targets(module, targets):

View File

@@ -121,8 +121,7 @@ def find_servicedelegationtarget(module, name):
except Exception: # pylint: disable=broad-except
# An exception is raised if servicedelegationtarget name is not found.
return None
else:
return _result["result"]
return _result["result"]
def main():

View File

@@ -122,8 +122,7 @@ def find_sudocmdgroup(module, name):
_result = module.ipa_command("sudocmdgroup_show", name, args)
except ipalib_errors.NotFound:
return None
else:
return _result["result"]
return _result["result"]
def gen_args(description, nomembers):

View File

@@ -977,12 +977,14 @@ def main():
changed = 'Archived data into' in result['summary']
elif command == 'vault_retrieve':
if 'result' not in result:
# pylint: disable=W0012,broad-exception-raised
raise Exception("No result obtained.")
if "data" in result["result"]:
data_return = exit_args.setdefault("vault", {})
data_return["data"] = result["result"]["data"]
else:
if not datafile_out:
# pylint: disable=W0012,broad-exception-raised
raise Exception("No data retrieved.")
changed = False
else:
@@ -993,7 +995,7 @@ def main():
changed = True
except ipalib_errors.EmptyModlist:
result = {}
except Exception as exception:
except Exception as exception: # pylint: disable=broad-except
ansible_module.fail_json(
msg="%s: %s: %s" % (command, name, str(exception)))

View File

@@ -1,10 +1,10 @@
-r requirements-tests.txt
ipdb==0.13.4
pre-commit==2.20.0
flake8==5.0.3
flake8-bugbear==22.10.27
pylint==2.14.4
wrapt == 1.14.0
pydocstyle==6.0.0
yamllint==1.28.0
ansible-lint==6.6.1
flake8==6.0.0
flake8-bugbear
pylint==2.17.2
wrapt==1.14.1
pydocstyle==6.3.0
yamllint==1.32.0
ansible-lint

View File

@@ -33,6 +33,7 @@ Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu 16.04 and 18.04
@@ -41,7 +42,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -6,7 +6,7 @@ galaxy_info:
description: A role to backup and restore an IPA server
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.8"
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:

View File

@@ -24,15 +24,17 @@ Supported Distributions
-----------------------
* RHEL/CentOS 7.4+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu
* Debian
Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -132,7 +132,7 @@ def main():
else:
get_ca_certs(fstore, options, servers[0], basedn, realm)
changed = True
del os.environ['KRB5_CONFIG']
os.environ.pop('KRB5_CONFIG', None)
except errors.FileError as e:
module.fail_json(msg='%s' % e)
except Exception as e:

View File

@@ -123,7 +123,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
"""Destroy temporary ticket and remove temporary ccache."""
if ccache_name is not None:
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
del os.environ['KRB5CCNAME']
os.environ.pop('KRB5CCNAME', None)
if ccache_dir is not None:
shutil.rmtree(ccache_dir, ignore_errors=True)

View File

@@ -272,7 +272,7 @@ def main():
get_ca_cert(fstore, options, servers[0], basedn)
else:
get_ca_certs(fstore, options, servers[0], basedn, realm)
del os.environ['KRB5_CONFIG']
os.environ.pop('KRB5_CONFIG', None)
except errors.FileError as e:
module.fail_json(msg='%s' % e)
except Exception as e:

View File

@@ -6,7 +6,7 @@ galaxy_info:
description: A role to join a machine to an IPA domain
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.8"
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:

View File

@@ -307,8 +307,7 @@ try:
else:
# IPA version < 4.4
raise Exception("freeipa version '%s' is too old" % VERSION)
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
except ImportError as _err:
ANSIBLE_IPA_CLIENT_MODULE_IMPORT_ERROR = str(_err)

View File

@@ -27,6 +27,7 @@ Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu 16.04 and 18.04
@@ -35,7 +36,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -669,7 +669,7 @@ def main():
raise errors.ACIError(info="Not authorized")
if installer._ccache is None:
del os.environ['KRB5CCNAME']
os.environ.pop('KRB5CCNAME', None)
else:
os.environ['KRB5CCNAME'] = installer._ccache
@@ -873,7 +873,7 @@ def main():
if add_to_ipaservers:
# use user's credentials when the server host is not ipaservers
if installer._ccache is None:
del os.environ['KRB5CCNAME']
os.environ.pop('KRB5CCNAME', None)
else:
os.environ['KRB5CCNAME'] = installer._ccache

View File

@@ -6,7 +6,7 @@ galaxy_info:
description: A role to setup an IPA domain replica
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.8"
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:

View File

@@ -171,8 +171,7 @@ try:
else:
# IPA version < 4.6
raise Exception("freeipa version '%s' is too old" % VERSION)
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
except ImportError as _err:
ANSIBLE_IPA_REPLICA_MODULE_IMPORT_ERROR = str(_err)

View File

@@ -24,6 +24,7 @@ Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu 16.04 and 18.04
@@ -32,7 +33,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

View File

@@ -108,7 +108,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
"""Destroy temporary ticket and remove temporary ccache."""
if ccache_name is not None:
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
del os.environ['KRB5CCNAME']
os.environ.pop('KRB5CCNAME', None)
if ccache_dir is not None:
shutil.rmtree(ccache_dir, ignore_errors=True)

View File

@@ -6,7 +6,7 @@ galaxy_info:
description: A role to setup an iPA domain server
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.8"
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:

View File

@@ -212,8 +212,7 @@ try:
else:
# IPA version < 4.5
raise Exception("freeipa version '%s' is too old" % VERSION)
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
except ImportError as _err:
ANSIBLE_IPA_SERVER_MODULE_IMPORT_ERROR = str(_err)

View File

@@ -24,6 +24,7 @@ Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
@@ -31,7 +32,7 @@ Requirements
------------
**Controller**
* Ansible version: 2.8+
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)

Some files were not shown because too many files have changed in this diff Show More