From 8bc6b01f49856f5c25bcd76ef6129a6947fad166 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 11:03:24 -0300 Subject: [PATCH 01/32] modules: Allow execution of plugins in an IPA client host. Add a new configuration variable, `ipaapi_context` to IPAAnsibleModule base specs, accepting only 'server' or 'client' values. By using this variable, an user can select the environment context in which the module will execute, server or client. This change will allow configuration of the server without requiring login access (e.g. `ssh`) to the server. The default behavior is to use a `server` context, but this behavior can be modified by the plugin, if it sets the `context` parameter when connecting to IPA API. --- plugins/doc_fragments/ipamodule_base_docs.py | 7 +++ .../module_utils/ansible_freeipa_module.py | 55 ++++++++++++++++--- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/plugins/doc_fragments/ipamodule_base_docs.py b/plugins/doc_fragments/ipamodule_base_docs.py index 22f2a1d1..4e8c1268 100644 --- a/plugins/doc_fragments/ipamodule_base_docs.py +++ b/plugins/doc_fragments/ipamodule_base_docs.py @@ -30,4 +30,11 @@ options: ipaadmin_password: description: The admin password. required: false + ipaapi_context: + description: | + 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. + choices: ["server", "client"] + required: false """ diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index fede14a5..fe526804 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -107,6 +107,34 @@ else: except ImportError: from collections import Mapping # pylint: disable=deprecated-class + # Try to import is_ipa_configured or use a fallback implementation. + try: + from ipalib.facts import is_ipa_configured + except ImportError: + try: + from ipaserver.install.installutils import is_ipa_configured + except ImportError: + from ipalib.install import sysrestore + + def is_ipa_configured(): + sstore = sysrestore.StateFile(paths.SYSRESTORE) + + if sstore.has_state('installation'): + return sstore.get_state('installation', 'complete') + + fstore = sysrestore.FileStore(paths.SYSRESTORE) + + IPA_MODULES = [ # pylint: disable=invalid-name + 'httpd', 'kadmin', 'dirsrv', 'pki-tomcatd', 'install', + 'krb5kdc', 'ntpd', 'named' + ] + + for module in IPA_MODULES: + if sstore.has_state(module): + return True + + return fstore.has_files() + if six.PY3: unicode = str @@ -179,18 +207,25 @@ else: `context` can be any of: * `server` (default) - * `ansible-freeipa` - * `cli_installer` + * `client` """ env = Env() env._bootstrap() env._finalize_core(**dict(DEFAULT_CONFIG)) - # available contexts are 'server', 'ansible-freeipa' and - # 'cli_installer' - + # If not set, context will be based on current API context. if context is None: - context = 'server' + context = "server" if is_ipa_configured() else "client" + + # Available contexts are 'server' and 'client'. + if context not in ["server", "client"]: + raise ValueError("Invalid execution context: %s" % (context)) + + # IPA uses 'cli' for a 'client' context, but 'client' + # provides a better user interface. Here we map the + # value if needed. + if context == "client": + context = "cli" api.bootstrap(context=context, debug=env.debug, log=None) api.finalize() @@ -577,6 +612,9 @@ else: ipa_module_base_spec = dict( ipaadmin_principal=dict(type="str", default="admin"), ipaadmin_password=dict(type="str", required=False, no_log=True), + ipaapi_context=dict( + type="str", required=False, choices=["server", "client"], + ), ) def __init__(self, *args, **kwargs): @@ -604,6 +642,8 @@ else: # ipaadmin vars ipaadmin_principal = self.params_get("ipaadmin_principal") ipaadmin_password = self.params_get("ipaadmin_password") + if context is None: + context = self.params_get("ipaapi_context") ccache_dir = None ccache_name = None @@ -1071,7 +1111,8 @@ else: def ipa_run(self): """Execute module actions.""" - with self.ipa_connect(): + ipaapi_context = self.ipa_params.get("ipaapi_context") + with self.ipa_connect(context=ipaapi_context): self.check_ipa_params() self.define_ipa_commands() self._run_ipa_commands() From 1c679c5a9a13151d8069ad386499fde688ad834b Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Wed, 8 Sep 2021 17:06:37 -0300 Subject: [PATCH 02/32] templates: Allow execution of plugins in an IPA client host. Modify templates to create the basic tests for `ipaapi_context: client`. --- utils/new_module | 1 + utils/templates/test_module+member.yml.in | 14 ++++++- utils/templates/test_module.yml.in | 9 ++++- .../test_module_client_context.yml.in | 39 +++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 utils/templates/test_module_client_context.yml.in diff --git a/utils/new_module b/utils/new_module index b6eecb27..882a9677 100755 --- a/utils/new_module +++ b/utils/new_module @@ -183,3 +183,4 @@ mkdir -p $dest src=test_module.yml.in [ $member == 1 ] && src=test_module+member.yml.in template $src $dest/test_$name.yml +template test_module_client_context.yml.in $dest/test_${name}_client_context.yml diff --git a/utils/templates/test_module+member.yml.in b/utils/templates/test_module+member.yml.in index f7c5b3d5..01012078 100644 --- a/utils/templates/test_module+member.yml.in +++ b/utils/templates/test_module+member.yml.in @@ -1,7 +1,10 @@ --- - name: Test $name - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" + # Change "become" or "gather_facts" to "yes", + # if you test playbook requires any. become: no + gather_facts: no tasks: @@ -20,6 +23,7 @@ - name: Ensure $name NAME is present ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME # Add needed parameters here register: result @@ -28,6 +32,7 @@ - name: Ensure $name NAME is present again ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME # Add needed parameters here register: result @@ -36,6 +41,7 @@ - name: Ensure $name NAME member PARAMETER2 VALUE is present ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME PARAMETER2: VALUE action: member @@ -45,6 +51,7 @@ - name: Ensure $name NAME member PARAMETER2 VALUE is present again ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME PARAMETER2: VALUE action: member @@ -54,6 +61,7 @@ - name: Ensure $name NAME member PARAMETER2 VALUE is absent ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME PARAMETER2: VALUE action: member @@ -64,6 +72,7 @@ - name: Ensure $name NAME member PARAMETER2 VALUE is absent again ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME PARAMETER2: VALUE action: member @@ -76,6 +85,7 @@ - name: Ensure $name NAME is absent ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME state: absent register: result @@ -84,6 +94,7 @@ - name: Ensure $name NAME is absent again ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME state: absent register: result @@ -94,5 +105,6 @@ - name: Ensure $name NAME is absent ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME state: absent diff --git a/utils/templates/test_module.yml.in b/utils/templates/test_module.yml.in index 0286813b..2ad53cc2 100644 --- a/utils/templates/test_module.yml.in +++ b/utils/templates/test_module.yml.in @@ -1,7 +1,10 @@ --- - name: Test $name - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" + # Change "become" or "gather_facts" to "yes", + # if you test playbook requires any. become: no + gather_facts: no tasks: @@ -10,6 +13,7 @@ - name: Ensure $name NAME is absent ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME state: absent @@ -28,6 +32,7 @@ - name: Ensure $name NAME is present again ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME # Add needed parameters here register: result @@ -38,6 +43,7 @@ - name: Ensure $name NAME is absent ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME state: absent register: result @@ -46,6 +52,7 @@ - name: Ensure $name NAME is absent again ipa$name: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: NAME state: absent register: result diff --git a/utils/templates/test_module_client_context.yml.in b/utils/templates/test_module_client_context.yml.in new file mode 100644 index 00000000..ee8c6789 --- /dev/null +++ b/utils/templates/test_module_client_context.yml.in @@ -0,0 +1,39 @@ +--- +- name: Test ${name} + hosts: ipaclients, ipaserver + # Change "become" or "gather_facts" to "yes", + # if you test playbook requires any. + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipa${name}: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test ${name} using client context, in client host. + import_playbook: test_${name}.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test ${name} using client context, in server host. + import_playbook: test_${name}.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From aa6c5c610bc0310960c12a7b05722e5ded078960 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Wed, 8 Sep 2021 17:16:48 -0300 Subject: [PATCH 03/32] tests: Create IPA fact ipa_host_is_client. This patch adds a new fact `ipa_host_is_client`, available in the include task file `env_freeipa_facts.yml`. The variable `ipa_host_is_client` is set to TRUE if the client host is not an IPA server (primary or replica). It can be used if a test cannot be executed in a server, independent of the value set to `ipaapi_context`. --- tests/env_freeipa_facts.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/env_freeipa_facts.yml b/tests/env_freeipa_facts.yml index 6622634d..a150ecd6 100644 --- a/tests/env_freeipa_facts.yml +++ b/tests/env_freeipa_facts.yml @@ -12,8 +12,20 @@ cmd: 'ipa --version | sed -n "s/VERSION: \([^,]*\).*API_VERSION: \([^,]*\).*/\1\\n\2/p"' register: ipa_cmd_version +- name: Verify if host is an IPA server or client. + shell: + cmd: | + echo SomeADMINpassword | kinit -c {{ KRB5CCNAME }} admin + RESULT=$(KRB5CCNAME={{ KRB5CCNAME }} ipa server-show `hostname` && echo SERVER || echo CLIENT) + kdestroy -A -c {{ KRB5CCNAME }} + echo $RESULT + vars: + KRB5CCNAME: "__check_ipa_host_is_client_or_server__" + register: output + - name: Set FreeIPA facts. set_fact: ipa_version: "{{ ipa_cmd_version.stdout_lines[0] }}" ipa_api_version: "{{ ipa_cmd_version.stdout_lines[1] }}" + ipa_host_is_client: "{{ (output.stdout_lines[-1] == 'CLIENT') | bool }}" trust_test_is_supported: no From e6ecae0d4baa37b2f61d3bfba8c183259dcb938e Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 12:14:19 -0300 Subject: [PATCH 04/32] ipaautomember: Allow execution of plugin in client host. Update automember README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/automember/test_automember_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-automember.md | 1 + tests/automember/test_automember.yml | 34 ++++++++++++++++- .../test_automember_client_context.yml | 38 +++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tests/automember/test_automember_client_context.yml diff --git a/README-automember.md b/README-automember.md index 7fbc62ce..0d2861e4 100644 --- a/README-automember.md +++ b/README-automember.md @@ -122,6 +122,7 @@ 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 `name` \| `cn` | Automember rule. | yes `description` | A description of this auto member rule. | no `automember_type` | Grouping to which the rule applies. It can be one of `group`, `hostgroup`. | yes diff --git a/tests/automember/test_automember.yml b/tests/automember/test_automember.yml index 24b8fb32..4f1516df 100644 --- a/tests/automember/test_automember.yml +++ b/tests/automember/test_automember.yml @@ -1,6 +1,6 @@ --- - name: Test automember - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -10,18 +10,21 @@ - name: Ensure group testgroup is absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup state: absent - name: Ensure hostgroup testhostgroup is absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup state: absent - name: Ensure group automember rule testgroup is absent ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup state: absent automember_type: group @@ -29,6 +32,7 @@ - name: Ensure hostgroup automember rule testhostgroup is absent ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup state: absent automember_type: hostgroup @@ -39,16 +43,19 @@ - name: Ensure testgroup group is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup - name: Ensure testhostgroup hostgroup is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup - name: Ensure testgroup group automember rule is present ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup description: testgroup automember rule. automember_type: group @@ -58,6 +65,7 @@ - name: Ensure testgroup group automember rule is present again ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup description: testgroup automember rule. automember_type: group @@ -67,6 +75,7 @@ - name: Change testgroup group automember rule description ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup description: testgroup automember rule description. automember_type: group @@ -76,6 +85,7 @@ - name: Ensure testgroup group automember rule has conditions ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group inclusive: @@ -92,6 +102,7 @@ - name: Ensure testgroup group automember rule has conditions again ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group inclusive: @@ -108,6 +119,7 @@ - name: Add testgroup group automember rule member condition ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group action: member @@ -120,6 +132,7 @@ - name: Ensure testgroup group automember rule has conditions ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group inclusive: @@ -138,6 +151,7 @@ - name: Remove testgroup group automember rule member condition ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group action: member @@ -151,6 +165,7 @@ - name: Ensure testgroup group automember rule has conditions again ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group inclusive: @@ -168,6 +183,7 @@ ipaautomember: ipaadmin_principal: admin ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group inclusive: @@ -182,6 +198,7 @@ ipaautomember: ipaadmin_principal: admin ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup automember_type: group exclusive: @@ -195,6 +212,7 @@ - name: Ensure testhostgroup hostgroup automember rule is present ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup description: testhostgroup automember rule automember_type: hostgroup @@ -204,6 +222,7 @@ - name: Ensure testhostgroup hostgroup automember rule is present again ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup description: testhostgroup automember rule automember_type: hostgroup @@ -213,6 +232,7 @@ - name: Change testhostgroup hostgroup automember rule description ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup description: testhostgroup test automember rule automember_type: hostgroup @@ -222,6 +242,7 @@ - name: Ensure testhostgroup hostgroup automember rule has conditions ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup inclusive: @@ -238,6 +259,7 @@ - name: Ensure testhostgroup hostgroup automember rule has conditions again ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup inclusive: @@ -254,6 +276,7 @@ - name: Add testhostgroup hostgroup automember rule member condition ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup action: member @@ -266,6 +289,7 @@ - name: Ensure testhostgroup hostgroup automember rule has conditions ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup inclusive: @@ -284,6 +308,7 @@ - name: Remove testhostgroup hostgroup automember rule member condition ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup action: member @@ -297,6 +322,7 @@ - name: Ensure testhostgroup hostgroup automember rule has conditions ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup inclusive: @@ -315,6 +341,7 @@ ipaautomember: ipaadmin_principal: admin ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup inclusive: @@ -329,6 +356,7 @@ ipaautomember: ipaadmin_principal: admin ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup automember_type: hostgroup exclusive: @@ -344,18 +372,21 @@ - name: Ensure group testgroup is absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup state: absent - name: Ensure hostgroup testhostgroup is absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup state: absent - name: Ensure group automember rule testgroup is absent ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" automember_type: group name: testgroup state: absent @@ -363,6 +394,7 @@ - name: Ensure hostgroup automember rule testhostgroup is absent ipaautomember: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" automember_type: hostgroup name: testhostgroup state: absent diff --git a/tests/automember/test_automember_client_context.yml b/tests/automember/test_automember_client_context.yml new file mode 100644 index 00000000..a3cd68d2 --- /dev/null +++ b/tests/automember/test_automember_client_context.yml @@ -0,0 +1,38 @@ +--- +- name: Test automember + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaautomember: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + state: rebuild + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test automember using client context, in client host. + import_playbook: test_automember.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test automember using client context, in server host. + import_playbook: test_automember.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From e4d2b62bdb7d820859d624306e65f4547f06facd Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:45:22 -0300 Subject: [PATCH 05/32] ipaautomountlocation: Allow execution of plugin in client host. Update automountlocation README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/automountlocation/test_automountlocation_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-automountlocation.md | 3 +- tests/automount/test_automountlocation.yml | 13 ++++++- .../test_automountlocation_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 tests/automount/test_automountlocation_client_context.yml diff --git a/README-automountlocation.md b/README-automountlocation.md index f28afc2a..42393bc1 100644 --- a/README-automountlocation.md +++ b/README-automountlocation.md @@ -88,7 +88,7 @@ Example playbook to ensure absence of an automount location: - name: ensure automount locations LOCATION1 and LOCATION2 do not exist ipaautomountlocation: ipaadmin_password: SomeADMINpassword - name: + name: - LOCATION1 - LOCATION2 state: absent @@ -104,6 +104,7 @@ 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 `name` \| `cn` \| `location` | List of one or more automountlocation names. | yes `state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no diff --git a/tests/automount/test_automountlocation.yml b/tests/automount/test_automountlocation.yml index 1eb11a65..7e6c3abb 100644 --- a/tests/automount/test_automountlocation.yml +++ b/tests/automount/test_automountlocation.yml @@ -1,6 +1,6 @@ --- - name: Test automountlocation - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,6 +8,7 @@ - name: ensure automountlocation TestLocations are absent before testing ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - TestLocation_01 - TestLocation_02 @@ -16,6 +17,7 @@ - name: ensure empty automountlocation does nothing ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: [] state: present register: result @@ -24,6 +26,7 @@ - name: ensure empty automountlocation does nothing on absent ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: [] state: absent register: result @@ -32,6 +35,7 @@ - name: ensure automountlocation TestLocation is present ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: TestLocation_01 state: present register: result @@ -40,6 +44,7 @@ - name: ensure automountlocation TestLocation is present again ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: TestLocation_01 state: present register: result @@ -48,6 +53,7 @@ - name: ensure automountlocation TestLocation is absent ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: TestLocation_01 state: absent register: result @@ -56,6 +62,7 @@ - name: ensure automountlocation TestLocation is absent again ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: TestLocation_01 state: absent register: result @@ -64,6 +71,7 @@ - name: ensure a list of automountlocations are present ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - TestLocation_01 - TestLocation_02 @@ -74,6 +82,7 @@ - name: ensure a list of automountlocations exist ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - TestLocation_01 - TestLocation_02 @@ -84,6 +93,7 @@ - name: ensure a list of automountlocations are absent ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - TestLocation_01 - TestLocation_02 @@ -94,6 +104,7 @@ - name: ensure multiple automountlocations are absent ipaautomountlocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - TestLocation_01 - TestLocation_02 diff --git a/tests/automount/test_automountlocation_client_context.yml b/tests/automount/test_automountlocation_client_context.yml new file mode 100644 index 00000000..ac534140 --- /dev/null +++ b/tests/automount/test_automountlocation_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test automountlocation + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test automountlocation using client context, in client host. + import_playbook: test_automountlocation.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test automountlocation using client context, in server host. + import_playbook: test_automountlocation.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 65271a018da37cbd1af70dc1ea6915294e186493 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 12:14:21 -0300 Subject: [PATCH 06/32] ipaconfig: Allow execution of plugin in client host. Update config README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/config/test_config_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. As the tests for ipaconfig may render the server in an inconsistent state if they fail, the tests in tests/config/test_config.yml were wrapped in a way that if one test fails, the default FreeIPA configuration is restored to the server. --- README-config.md | 1 + tests/config/test_config.yml | 58 ++++++++++++++++++++- tests/config/test_config_client_context.yml | 36 +++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 tests/config/test_config_client_context.yml diff --git a/README-config.md b/README-config.md index c6b570fe..f7a5b681 100644 --- a/README-config.md +++ b/README-config.md @@ -91,6 +91,7 @@ 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 `maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | no `maxhostname` \| `ipamaxhostnamelength` | Set the maximum hostname length between 64-255. Only usable with IPA versions 4.8.0 and up. | no `homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | no diff --git a/tests/config/test_config.yml b/tests/config/test_config.yml index 54a572eb..01c1913f 100644 --- a/tests/config/test_config.yml +++ b/tests/config/test_config.yml @@ -1,6 +1,6 @@ --- - name: Playbook to handle server configuration - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -12,6 +12,7 @@ - name: return current values of the global configuration options ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" register: previousconfig - debug: @@ -21,94 +22,112 @@ - name: create test group ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: somedefaultgroup - name: Ensure the default e-mail domain is ipa.test. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" emaildomain: ipa.test - name: set default shell to '/bin/sh' ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" defaultshell: /bin/sh - name: set default group ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" defaultgroup: ipausers - name: set default home directory ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" homedirectory: /home - name: clear pac-type ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" pac_type: "" - name: set maxhostname to 255 block: - ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxhostname: 255 when: ipa_version is version('4.8.0', '>=') - name: set maxusername to 45 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxusername: 45 - name: set pwdexpnotify to 0 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" pwdexpnotify: 0 - name: set searchrecordslimit to 10 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" searchrecordslimit: 10 - name: set searchtimelimit to 1 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" searchtimelimit: 1 - name: clear configstring ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" configstring: "" - name: set configstring to AllowNThash ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" configstring: 'KDC:Disable Lockout' - name: set selinuxusermapdefault ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" selinuxusermapdefault: "staff_u:s0-s0:c0.c1023" - name: set selinuxusermaporder ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023' - name: set usersearch to `uid` ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" usersearch: uid - name: set groupsearch to `cn` ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" groupsearch: cn # tests - name: Ensure the default e-mail domain is somedomain.test. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" emaildomain: somedomain.test register: result failed_when: not result.changed or result.failed @@ -116,6 +135,7 @@ - name: Ensure the default e-mail domain is somedomain.test, again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" emaildomain: somedomain.test register: result failed_when: result.changed or result.failed @@ -123,6 +143,7 @@ - name: set default shell to '/bin/someshell' ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" defaultshell: /bin/someshell register: result failed_when: not result.changed or result.failed @@ -130,6 +151,7 @@ - name: set default shell to '/bin/someshell', again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" defaultshell: /bin/someshell register: result failed_when: result.changed or result.failed @@ -137,6 +159,7 @@ - name: set default group ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" defaultgroup: somedefaultgroup register: result failed_when: not result.changed or result.failed @@ -144,6 +167,7 @@ - name: set default group, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" defaultgroup: somedefaultgroup register: result failed_when: result.changed or result.failed @@ -151,6 +175,7 @@ - name: set default home directory ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" homedirectory: /Users register: result failed_when: not result.changed or result.failed @@ -158,6 +183,7 @@ - name: set default home directory, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" homedirectory: /Users register: result failed_when: result.changed or result.failed @@ -165,6 +191,7 @@ - name: set pac-type ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" pac_type: "nfs:NONE" register: result failed_when: not result.changed or result.failed @@ -172,6 +199,7 @@ - name: set pac-type, again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" pac_type: "nfs:NONE" register: result failed_when: result.changed or result.failed @@ -179,6 +207,7 @@ - name: set maxusername to 33 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxusername: 33 register: result failed_when: not result.changed or result.failed @@ -186,6 +215,7 @@ - name: set maxusername to 33, again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxusername: 33 register: result failed_when: result.changed or result.failed @@ -194,12 +224,14 @@ block: - ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxhostname: 77 register: result failed_when: not result.changed or result.failed - ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxhostname: 77 register: result failed_when: result.changed or result.failed @@ -208,6 +240,7 @@ - name: set pwdexpnotify to 17 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" pwdexpnotify: 17 register: result failed_when: not result.changed or result.failed @@ -215,6 +248,7 @@ - name: set pwdexpnotify to 17, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" pwdexpnotify: 17 register: result failed_when: result.changed or result.failed @@ -222,6 +256,7 @@ - name: set searchrecordslimit to -1 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" searchrecordslimit: -1 register: result failed_when: not result.changed or result.failed @@ -229,6 +264,7 @@ - name: set searchrecordslimit to -1, again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" searchrecordslimit: -1 register: result failed_when: result.changed or result.failed @@ -236,6 +272,7 @@ - name: set searchtimelimit to 12345 ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" searchtimelimit: 12345 register: result failed_when: not result.changed or result.failed @@ -243,6 +280,7 @@ - name: set searchtimelimit to 12345, again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" searchtimelimit: 12345 register: result failed_when: result.changed or result.failed @@ -250,6 +288,7 @@ - name: change enable_migration ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" enable_migration: '{{ not (previousconfig.config.enable_migration | bool) }}' register: result failed_when: not result.changed or result.failed @@ -257,6 +296,7 @@ - name: change enable_migration, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" enable_migration: '{{ not (previousconfig.config.enable_migration | bool) }}' register: result failed_when: result.changed or result.failed @@ -264,6 +304,7 @@ - name: set configstring to AllowNThash ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" configstring: AllowNThash register: result failed_when: not result.changed or result.failed @@ -271,6 +312,7 @@ - name: set configstring to AllowNThash, again. ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" configstring: AllowNThash register: result failed_when: result.changed or result.failed @@ -278,6 +320,7 @@ - name: set selinuxusermaporder ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023' register: result failed_when: not result.changed or result.failed @@ -285,6 +328,7 @@ - name: set selinuxusermaporder, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023' register: result failed_when: result.changed or result.failed @@ -292,6 +336,7 @@ - name: set selinuxusermapdefault ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" selinuxusermapdefault: 'user_u:s0' register: result failed_when: not result.changed or result.failed @@ -299,6 +344,7 @@ - name: set selinuxusermapdefault, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" selinuxusermapdefault: 'user_u:s0' register: result failed_when: result.changed or result.failed @@ -306,6 +352,7 @@ - name: set groupsearch to `description` ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" groupsearch: description register: result failed_when: not result.changed or result.failed @@ -313,6 +360,7 @@ - name: set groupsearch to `gidNumber`, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" groupsearch: description register: result failed_when: result.changed or result.failed @@ -320,6 +368,7 @@ - name: set usersearch to `uidNumber` ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" usersearch: uidNumber register: result failed_when: not result.changed or result.failed @@ -327,6 +376,7 @@ - name: set usersearch to `uidNumber`, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" usersearch: uidNumber register: result failed_when: result.changed or result.failed @@ -334,6 +384,7 @@ - name: reset changed fields ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxusername: '{{ previousconfig.config.maxusername | default(32) | int }}' homedirectory: '{{ previousconfig.config.homedirectory | default(omit) }}' defaultshell: '{{ previousconfig.config.defaultshell | default(omit) }}' @@ -361,12 +412,14 @@ block: - ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxhostname: '{{ previousconfig.config.maxhostname | default(omit) }}' when: ipa_version is version('4.8.0', '>=') - name: reset changed fields, again ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxusername: '{{ previousconfig.config.maxusername | default(omit) | int }}' homedirectory: '{{ previousconfig.config.homedirectory | default(omit) }}' defaultshell: '{{ previousconfig.config.defaultshell | default(omit) }}' @@ -394,6 +447,7 @@ block: - ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxhostname: '{{ previousconfig.config.maxhostname | default(omit) }}' when: ipa_version is version('4.8.0', '>=') @@ -401,6 +455,7 @@ - name: Set fields to IPA default, due to error ipaconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxusername: '{{ previousconfig.config.maxusername | default(omit) | int }}' homedirectory: '{{ previousconfig.config.homedirectory | default(omit) }}' defaultshell: '{{ previousconfig.config.defaultshell | default(omit) }}' @@ -431,5 +486,6 @@ - name: cleanup test group ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: somedefaultgroup state: absent diff --git a/tests/config/test_config_client_context.yml b/tests/config/test_config_client_context.yml new file mode 100644 index 00000000..589105f8 --- /dev/null +++ b/tests/config/test_config_client_context.yml @@ -0,0 +1,36 @@ +--- +- name: Test config + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test config using client context, in client host. + import_playbook: test_config.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test config using client context, in server host. + import_playbook: test_config.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 638977e0b8da0f5cc515d6674dafba20a7bbea14 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 12:14:25 -0300 Subject: [PATCH 07/32] ipadelegation: Allow execution of plugin in client host. Update delegation README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/delegation/test_delegation_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-delegation.md | 1 + tests/delegation/test_delegation.yml | 29 ++++++++++++++- .../test_delegation_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/delegation/test_delegation_client_context.yml diff --git a/README-delegation.md b/README-delegation.md index 63e4150b..00d84388 100644 --- a/README-delegation.md +++ b/README-delegation.md @@ -142,6 +142,7 @@ 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 `name` \| `aciname` | The list of delegation name strings. | yes `permission` \| `permissions` | The permission to grant `read`, `read,write`, `write`]. Default is `write`. | no `attribute` \| `attrs` | The attribute list to which the delegation applies. | no diff --git a/tests/delegation/test_delegation.yml b/tests/delegation/test_delegation.yml index 4f609b8a..6bd0df7f 100644 --- a/tests/delegation/test_delegation.yml +++ b/tests/delegation/test_delegation.yml @@ -1,6 +1,6 @@ --- - name: Test delegation - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -10,12 +10,14 @@ - name: Ensure test groups are absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: managers,managers2,employees,employees2 state: absent - name: Ensure delegation "basic manager attributes" is absent ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" state: absent @@ -24,21 +26,25 @@ - name: Ensure test group managers is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: managers - name: Ensure test group managers2 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: managers2 - name: Ensure test group employees is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: employees - name: Ensure test group employees2 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: employees2 # TESTS @@ -46,6 +52,7 @@ - name: Ensure delegation "basic manager attributes" is present ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read attribute: @@ -58,6 +65,7 @@ - name: Ensure delegation "basic manager attributes" is present again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read attribute: @@ -70,6 +78,7 @@ - name: Ensure delegation "basic manager attributes" is present with different attribute employeetype ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read attribute: @@ -82,6 +91,7 @@ - name: Ensure delegation "basic manager attributes" is present with different attribute employeetype again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read attribute: @@ -94,6 +104,7 @@ - name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - departmentnumber @@ -104,6 +115,7 @@ - name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - departmentnumber @@ -114,6 +126,7 @@ - name: Ensure delegation "basic manager attributes" member attributes employeetype and employeenumber are present ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - employeetype @@ -125,6 +138,7 @@ - name: Ensure delegation "basic manager attributes" member attributes employeetype and employeenumber are present again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - employeetype @@ -136,6 +150,7 @@ - name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - employeenumber @@ -148,6 +163,7 @@ - name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - employeenumber @@ -162,6 +178,7 @@ - name: Ensure delegation "basic manager attributes" is present with different read,write permission ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read,write attribute: @@ -174,6 +191,7 @@ - name: Ensure delegation "basic manager attributes" is present with different read,write permission again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read,write attribute: @@ -186,6 +204,7 @@ - name: Ensure delegation "basic manager attributes" is present with different group managers2 ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" group: managers2 register: result @@ -194,6 +213,7 @@ - name: Ensure delegation "basic manager attributes" is present with different group managers2 again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" group: managers2 register: result @@ -202,6 +222,7 @@ - name: Ensure delegation "basic manager attributes" is present with different membergroup employees2 ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" membergroup: employees2 register: result @@ -210,6 +231,7 @@ - name: Ensure delegation "basic manager attributes" is present with different membergroup employees2 again ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" membergroup: employees2 register: result @@ -218,6 +240,7 @@ - name: Ensure delegation "basic manager attributes" fails with bad permission read,read ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read,read register: result @@ -226,6 +249,7 @@ - name: Ensure delegation "basic manager attributes" fails with bad permission read,write,write ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" permission: read,write,write register: result @@ -234,6 +258,7 @@ - name: Ensure delegation "basic manager attributes" fails with bad attribute businesscategory,businesscategory ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" attribute: - businesscategory @@ -246,11 +271,13 @@ - name: Ensure delegation "basic manager attributes" is absent ipadelegation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "basic manager attributes" state: absent - name: Ensure test groups are absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: managers,managers2,employees,employees2 state: absent diff --git a/tests/delegation/test_delegation_client_context.yml b/tests/delegation/test_delegation_client_context.yml new file mode 100644 index 00000000..8756897d --- /dev/null +++ b/tests/delegation/test_delegation_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test delegation + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipadelegation: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test delegation using client context, in client host. + import_playbook: test_delegation.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test delegation using client context, in server host. + import_playbook: test_delegation.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 393cb8ba823c6c106eb56c722b1b8f83cbcf9404 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 12:14:28 -0300 Subject: [PATCH 08/32] ipadnsconfig: Allow execution of plugin in client host. Update dnsconfig README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/dnsconfig/test_dnsconfig_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-dnsconfig.md | 1 + tests/dnsconfig/test_dnsconfig.yml | 21 ++++++++++- .../test_dnsconfig_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/dnsconfig/test_dnsconfig_client_context.yml diff --git a/README-dnsconfig.md b/README-dnsconfig.md index 029ec515..f7e733fb 100644 --- a/README-dnsconfig.md +++ b/README-dnsconfig.md @@ -126,6 +126,7 @@ 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 `forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no   | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes   | `port` - The custom port that should be used on this server. | no diff --git a/tests/dnsconfig/test_dnsconfig.yml b/tests/dnsconfig/test_dnsconfig.yml index 3a69bea8..b416a0d1 100644 --- a/tests/dnsconfig/test_dnsconfig.yml +++ b/tests/dnsconfig/test_dnsconfig.yml @@ -1,6 +1,6 @@ --- - name: Test dnsconfig - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: true @@ -9,6 +9,7 @@ - name: Ensure forwarders are absent. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 - ip_address: 8.8.4.4 @@ -21,6 +22,7 @@ - name: Set config to invalid IPv4. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 1.2.3.500 register: result @@ -29,6 +31,7 @@ - name: Set config to invalid IP. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 1.in.va.lid register: result @@ -37,6 +40,7 @@ - name: Set config to invalid IPv6. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: fd00::invalid register: result @@ -45,6 +49,7 @@ - name: Set dnsconfig. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 - ip_address: 8.8.4.4 @@ -58,6 +63,7 @@ - name: Set dnsconfig, with the same values. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 - ip_address: 8.8.4.4 @@ -71,6 +77,7 @@ - name: Ensure forwarder is absent. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 state: absent @@ -80,6 +87,7 @@ - name: Ensure forwarder is absent, again. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 state: absent @@ -89,6 +97,7 @@ - name: Disable global forwarders. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forward_policy: none register: result failed_when: not result.changed or result.failed @@ -96,6 +105,7 @@ - name: Disable global forwarders, again. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forward_policy: none register: result failed_when: result.changed or result.failed @@ -103,6 +113,7 @@ - name: Re-enable global forwarders. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forward_policy: first register: result failed_when: not result.changed or result.failed @@ -110,6 +121,7 @@ - name: Re-enable global forwarders, again. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forward_policy: first register: result failed_when: result.changed or result.failed @@ -117,6 +129,7 @@ - name: Disable PTR record synchronization. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" allow_sync_ptr: no register: result failed_when: not result.changed or result.failed @@ -124,6 +137,7 @@ - name: Disable PTR record synchronization, again. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" allow_sync_ptr: no register: result failed_when: result.changed or result.failed @@ -131,6 +145,7 @@ - name: Re-enable PTR record synchronization. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" allow_sync_ptr: yes register: result failed_when: not result.changed or result.failed @@ -138,6 +153,7 @@ - name: Re-enable PTR record synchronization, again. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" allow_sync_ptr: yes register: result failed_when: result.changed or result.failed @@ -145,6 +161,7 @@ - name: Ensure all forwarders are absent. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 - ip_address: 8.8.4.4 @@ -158,6 +175,7 @@ - name: Ensure all forwarders are absent, again. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 - ip_address: 8.8.4.4 @@ -171,6 +189,7 @@ - name: Ensure forwarders are absent. ipadnsconfig: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" forwarders: - ip_address: 8.8.8.8 - ip_address: 8.8.4.4 diff --git a/tests/dnsconfig/test_dnsconfig_client_context.yml b/tests/dnsconfig/test_dnsconfig_client_context.yml new file mode 100644 index 00000000..6db3b62a --- /dev/null +++ b/tests/dnsconfig/test_dnsconfig_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test dnsconfig + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipadnsconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + forward_policy: none + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test dnsconfig using client context, in client host. + import_playbook: test_dnsconfig.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test dnsconfig using client context, in server host. + import_playbook: test_dnsconfig.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From da45d74f7549d622df8c7993900a2347c4777e4b Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 12:14:30 -0300 Subject: [PATCH 09/32] ipadnsforwardzone: Allow execution of plugin in client host. Update dnsforwardzone README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/dnsforwardzone/test_dnsforwardzone_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. Due to differences in data returned when running ipadnsforwardzone in a client context, some values had to be modified so that comparision works, avoiding unnecessary IPA API calls. --- README-dnsforwardzone.md | 1 + plugins/modules/ipadnsforwardzone.py | 14 +++++++ tests/dnsforwardzone/test_dnsforwardzone.yml | 36 +++++++++++++++++- .../test_dnsforwardzone_client_context.yml | 37 +++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 tests/dnsforwardzone/test_dnsforwardzone_client_context.yml diff --git a/README-dnsforwardzone.md b/README-dnsforwardzone.md index 24986081..cd5b5cc5 100644 --- a/README-dnsforwardzone.md +++ b/README-dnsforwardzone.md @@ -107,6 +107,7 @@ 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 `name` \| `cn` | Zone name (FQDN). | yes if `state` == `present` `forwarders` \| `idnsforwarders` | Per-zone forwarders. A custom port can be specified for each forwarder. Options | no   | `ip_address`: The forwarder IP address. | yes diff --git a/plugins/modules/ipadnsforwardzone.py b/plugins/modules/ipadnsforwardzone.py index f6d4a24d..492a3173 100644 --- a/plugins/modules/ipadnsforwardzone.py +++ b/plugins/modules/ipadnsforwardzone.py @@ -160,6 +160,19 @@ def forwarder_list(forwarders): return fwd_list +def fix_resource_data_types(resource): + """Fix resource data types.""" + # When running in client context, some data might + # not come as a list, so we need to fix it before + # applying any modifications to it. + forwarders = resource["idnsforwarders"] + if isinstance(forwarders, str): + forwarders = [forwarders] + elif isinstance(forwarders, tuple): + forwarders = list(forwarders) + resource["idnsforwarders"] = forwarders + + def main(): ansible_module = IPAAnsibleModule( argument_spec=dict( @@ -288,6 +301,7 @@ def main(): continue else: # existing_resource is not None + fix_resource_data_types(existing_resource) if state != "absent": if forwarders: forwarders = list( diff --git a/tests/dnsforwardzone/test_dnsforwardzone.yml b/tests/dnsforwardzone/test_dnsforwardzone.yml index b9569faa..260829ff 100644 --- a/tests/dnsforwardzone/test_dnsforwardzone.yml +++ b/tests/dnsforwardzone/test_dnsforwardzone.yml @@ -1,6 +1,6 @@ --- - name: Test dnsforwardzone - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,6 +8,7 @@ - name: ensure test forwardzones are absent ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - example.com - newfailzone.com @@ -16,6 +17,7 @@ - name: ensure forwardzone example.com is created ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -28,6 +30,7 @@ - name: ensure forwardzone example.com is present again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -40,6 +43,7 @@ - name: ensure forwardzone example.com has two forwarders ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -54,6 +58,7 @@ - name: ensure forwardzone example.com has one forwarder again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com forwarders: - ip_address: 8.8.8.8 @@ -66,6 +71,7 @@ - name: skip_overlap_check can only be set on creation so change nothing ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com forwarders: - ip_address: 8.8.8.8 @@ -78,6 +84,7 @@ - name: ensure forwardzone example.com is absent. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: absent register: result @@ -86,6 +93,7 @@ - name: ensure forwardzone example.com is absent, again. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: absent register: result @@ -94,6 +102,7 @@ - name: change all the things at once ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -109,6 +118,7 @@ - name: change zone forward policy ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com forwardpolicy: first register: result @@ -117,6 +127,7 @@ - name: change zone forward policy, again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com forwardpolicy: first register: result @@ -125,6 +136,7 @@ - name: ensure forwardzone example.com is absent. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: absent register: result @@ -133,6 +145,7 @@ - name: ensure forwardzone example.com is absent, again. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: absent register: result @@ -141,6 +154,7 @@ - name: ensure forwardzone example.com is created with minimal args ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com skip_overlap_check: true @@ -152,6 +166,7 @@ - name: ensure forwardzone example.com is created with minimal args, again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com skip_overlap_check: true @@ -163,6 +178,7 @@ - name: add a forwarder to any existing ones ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -175,6 +191,7 @@ - name: add a forwarder to any existing ones, again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -187,6 +204,7 @@ - name: check the list of forwarders is what we expect ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -200,6 +218,7 @@ - name: remove a single forwarder ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: absent name: example.com forwarders: @@ -211,6 +230,7 @@ - name: remove a single forwarder, again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: absent name: example.com forwarders: @@ -222,6 +242,7 @@ - name: check the list of forwarders is what we expect now ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -234,6 +255,7 @@ - name: Add a permission for per-forward zone access delegation. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com permission: yes action: member @@ -243,6 +265,7 @@ - name: Add a permission for per-forward zone access delegation, again. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com permission: yes action: member @@ -252,6 +275,7 @@ - name: Remove a permission for per-forward zone access delegation. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com permission: no action: member @@ -261,6 +285,7 @@ - name: Remove a permission for per-forward zone access delegation, again. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com permission: no action: member @@ -270,6 +295,7 @@ - name: disable the forwarder ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: disabled register: result @@ -278,6 +304,7 @@ - name: disable the forwarder again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: disabled register: result @@ -286,6 +313,7 @@ - name: enable the forwarder ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: enabled register: result @@ -294,6 +322,7 @@ - name: enable the forwarder, again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: enabled register: result @@ -302,12 +331,14 @@ - name: ensure forwardzone example.com is absent again ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: absent - name: try to create a new forwarder with action=member ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: present name: example.com forwarders: @@ -321,6 +352,7 @@ - name: try to create a new forwarder with disabled state ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: example.com state: disabled register: result @@ -329,6 +361,7 @@ - name: Ensure forwardzone is not added without forwarders, with correct message. ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: newfailzone.com register: result failed_when: not result.failed or "No forwarders specified" not in result.msg @@ -336,6 +369,7 @@ - name: ensure forwardzone example.com is absent - tidy up ipadnsforwardzone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - example.com - newfailzone.com diff --git a/tests/dnsforwardzone/test_dnsforwardzone_client_context.yml b/tests/dnsforwardzone/test_dnsforwardzone_client_context.yml new file mode 100644 index 00000000..23b536e2 --- /dev/null +++ b/tests/dnsforwardzone/test_dnsforwardzone_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test dnsforwardzone + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipadnsforwardzone: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test dnsforwardzone using client context, in client host. + import_playbook: test_dnsforwardzone.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test dnsforwardzone using client context, in server host. + import_playbook: test_dnsforwardzone.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From a834de1f956f940d2a32f0faa33d5ad688551b6e Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:26:01 -0300 Subject: [PATCH 10/32] ipadnsrecord: Allow execution of plugin in client host. Update dnsrecord README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/dnsrecord/test_dnsrecord_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-dnsrecord.md | 1 + tests/dnsrecord/env_cleanup.yml | 259 +++++++++--------- tests/dnsrecord/env_setup.yml | 2 + tests/dnsrecord/test_dnsrecord.yml | 133 ++++++++- .../test_dnsrecord_client_context.yml | 37 +++ 5 files changed, 306 insertions(+), 126 deletions(-) create mode 100644 tests/dnsrecord/test_dnsrecord_client_context.yml diff --git a/README-dnsrecord.md b/README-dnsrecord.md index 6f88f432..35c3614c 100644 --- a/README-dnsrecord.md +++ b/README-dnsrecord.md @@ -249,6 +249,7 @@ 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 `zone_name` \| `dnszone` | The DNS zone name to which DNS record needs to be managed. You can use one global zone name for multiple records. | no required: true `records` | The list of dns records dicts. Each `records` dict entry can contain **record variables**. | no diff --git a/tests/dnsrecord/env_cleanup.yml b/tests/dnsrecord/env_cleanup.yml index c5890fa0..b74aca35 100644 --- a/tests/dnsrecord/env_cleanup.yml +++ b/tests/dnsrecord/env_cleanup.yml @@ -1,135 +1,144 @@ --- # Cleanup tasks. - - name: Ensure that dns records are absent - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: "{{ testzone }}" - del_all: yes - name: - - host01 - - host02 - - host03 - - host04 - - _ftp._tcp - - _sip._udp - state: absent + - name: Ensure that dns records are absent + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: "{{ testzone }}" + del_all: yes + name: + - host01 + - host02 + - host03 + - host04 + - _ftp._tcp + - _sip._udp + state: absent - - name: Ensure that dns reverse ipv6 records are absent - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: ip6.arpa. - del_all: yes - name: - - 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f - - 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f - - 1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f - - 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f - - 4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f - - 4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f - state: absent + - name: Ensure that dns reverse ipv6 records are absent + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: ip6.arpa. + del_all: yes + name: + - 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f + - 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f + - 1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f + - 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f + - 4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f + - 4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f + state: absent - - name: Ensure that dns reverse ipv6 records are absent (workaround) - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: "{{ zone_ipv6_reverse_workaround }}" - del_all: yes - name: - - 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 - - 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 - - 1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 - - 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 - - 4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 - - 4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 - state: absent + - name: Ensure that dns reverse ipv6 records are absent (workaround) + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: "{{ zone_ipv6_reverse_workaround }}" + del_all: yes + name: + - 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + - 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + - 1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + - 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + - 4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + - 4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + state: absent - - name: Ensure that dns reverse records are absent - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: "{{ zone_prefix_reverse_24 }}" - name: - - "101" - - "102" - - "103" - - "104" - - "111" - - "112" - - "113" - - "114" - - "121" - - "122" - - "123" - - "124" - del_all: yes - state: absent + - name: Ensure that dns reverse records are absent + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: "{{ zone_prefix_reverse_24 }}" + name: + - "101" + - "102" + - "103" + - "104" + - "111" + - "112" + - "113" + - "114" + - "121" + - "122" + - "123" + - "124" + del_all: yes + state: absent - - name: Ensure that dns reverse records are absent (workaround 1) - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: "{{ zone_prefix_reverse_16 }}" - name: - - "101.122" - - "102.122" - - "103.122" - - "104.122" - - "111.122" - - "112.122" - - "113.122" - - "114.122" - - "121.122" - - "122.122" - - "123.122" - - "124.122" - del_all: yes - state: absent + - name: Ensure that dns reverse records are absent (workaround 1) + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: "{{ zone_prefix_reverse_16 }}" + name: + - "101.122" + - "102.122" + - "103.122" + - "104.122" + - "111.122" + - "112.122" + - "113.122" + - "114.122" + - "121.122" + - "122.122" + - "123.122" + - "124.122" + del_all: yes + state: absent - - name: Ensure that dns reverse records are absent (workaround 2) - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: "{{ zone_prefix_reverse_8 }}" - name: - - "168.101.122" - - "168.102.122" - - "168.103.122" - - "168.104.122" - - "168.111.122" - - "168.112.122" - - "168.113.122" - - "168.114.122" - - "168.121.122" - - "168.122.122" - - "168.123.122" - - "168.124.122" - del_all: yes - state: absent + - name: Ensure that dns reverse records are absent (workaround 2) + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: "{{ zone_prefix_reverse_8 }}" + name: + - "168.101.122" + - "168.102.122" + - "168.103.122" + - "168.104.122" + - "168.111.122" + - "168.112.122" + - "168.113.122" + - "168.114.122" + - "168.121.122" + - "168.122.122" + - "168.123.122" + - "168.124.122" + del_all: yes + state: absent - - name: Ensure that "{{ safezone }}" dns records are absent - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - zone_name: "{{ safezone }}" - records: - - name: iron01 - del_all: yes - state: absent + - name: Ensure that "{{ safezone }}" dns records are absent + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + zone_name: "{{ safezone }}" + records: + - name: iron01 + del_all: yes + state: absent - - name: Ensure that NS record for "{{ safezone }}" is absent - ipadnsrecord: - ipaadmin_password: SomeADMINpassword - name: iron01 - zone_name: "{{ safezone }}" - ns_rec: iron01 - state: absent + - name: Ensure that NS record for "{{ safezone }}" is absent + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: iron01 + zone_name: "{{ safezone }}" + ns_rec: iron01 + state: absent - - name: Ensure DNS testing zones are absent. - ipadnszone: - ipaadmin_password: SomeADMINpassword - name: "{{ item }}" - state: absent - with_items: - - "{{ zone_prefix_reverse }}" - - "{{ zone_prefix_reverse_24 }}" - - "{{ zone_prefix_reverse_16 }}" - - "{{ zone_prefix_reverse_8 }}" - - "{{ zone_ipv6_reverse }}" - - "{{ zone_ipv6_reverse_workaround }}" - - "{{ testzone }}" - - "{{ safezone }}" + - name: Ensure DNS testing zones are absent. + ipadnszone: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: "{{ item }}" + state: absent + with_items: + - "{{ zone_prefix_reverse }}" + - "{{ zone_prefix_reverse_24 }}" + - "{{ zone_prefix_reverse_16 }}" + - "{{ zone_prefix_reverse_8 }}" + - "{{ zone_ipv6_reverse }}" + - "{{ zone_ipv6_reverse_workaround }}" + - "{{ testzone }}" + - "{{ safezone }}" diff --git a/tests/dnsrecord/env_setup.yml b/tests/dnsrecord/env_setup.yml index ebdb7570..0c2cfdff 100644 --- a/tests/dnsrecord/env_setup.yml +++ b/tests/dnsrecord/env_setup.yml @@ -10,6 +10,7 @@ - name: Ensure DNS testing zones are present. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item }}" skip_nameserver_check: yes skip_overlap_check: yes @@ -25,6 +26,7 @@ - name: Ensure DNSSEC zone '"{{ safezone }}"' is present. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ safezone }}" dnssec: yes skip_nameserver_check: yes diff --git a/tests/dnsrecord/test_dnsrecord.yml b/tests/dnsrecord/test_dnsrecord.yml index 5b5d48a9..176e5492 100644 --- a/tests/dnsrecord/test_dnsrecord.yml +++ b/tests/dnsrecord/test_dnsrecord.yml @@ -1,6 +1,6 @@ --- - name: Test dnsrecord - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: yes gather_facts: yes @@ -23,6 +23,7 @@ - name: Ensure that dns record 'host01' is present ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: host01 zone_name: "{{ testzone }}" record_type: AAAA @@ -33,6 +34,7 @@ - name: Ensure that dns record 'host01' is present, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: host01 zone_name: "{{ testzone }}" record_type: AAAA @@ -43,6 +45,7 @@ - name: Ensure that dns record 'host02' is present ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: host02 zone_name: "{{ testzone }}" record_type: A @@ -53,6 +56,7 @@ - name: Ensure that dns record 'host02' is present, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: host02 zone_name: "{{ testzone }}" record_type: A @@ -63,6 +67,7 @@ - name: Modify record 'host02' with multiple A and AAAA record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" records: - name: host02 zone_name: "{{ testzone }}" @@ -80,6 +85,7 @@ - name: Modify record 'host02' with multiple A and AAAA record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" records: - name: host02 zone_name: "{{ testzone }}" @@ -97,6 +103,7 @@ - name: Ensure 'host02' A6 record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host02 a6_data: ::1 @@ -106,6 +113,7 @@ - name: Ensure 'host02' A6 record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host02 a6_rec: ::1 @@ -115,6 +123,7 @@ - name: Ensure 'host02' A6 record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host02 a6_rec: ::1 @@ -125,6 +134,7 @@ - name: Ensure 'host02' A6 record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host02 a6_rec: ::1 @@ -135,6 +145,7 @@ - name: Ensure that dns record 'host03' is present, with reverse record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: host03 zone_name: "{{ testzone }}" a_ip_address: "{{ ipv4_prefix }}.103" @@ -145,6 +156,7 @@ - name: Ensure that dns record 'host03' is present, with reverse record, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: host03 zone_name: "{{ testzone }}" record_type: A @@ -156,6 +168,7 @@ - name: Delete all entries associated with host03 ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host03 del_all: yes @@ -166,6 +179,7 @@ - name: Delete all entries associated with host03, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host03 del_all: yes @@ -176,6 +190,7 @@ - name: Ensure that 'host04' has CNAME ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 record_type: CNAME @@ -186,6 +201,7 @@ - name: Ensure that 'host04' has CNAME, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cname_hostname: "host04.{{ testzone }}" @@ -195,6 +211,7 @@ - name: Ensure that 'host04' CNAME is absent ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cname_rec: "host04.{{ testzone }}" @@ -205,6 +222,7 @@ - name: Ensure that 'host04' CNAME is absent, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 record_type: CNAME @@ -216,6 +234,7 @@ - name: Ensure that 'host04' and 'host03' have CNAME, with cname_hostname ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" records: - name: host04 @@ -228,6 +247,7 @@ - name: Ensure that 'host04' has CNAME, with cname_hostname, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cname_hostname: "host04.{{ testzone }}" @@ -237,6 +257,7 @@ - name: Ensure that 'host04' CNAME is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cname_rec: "host04.{{ testzone }}" @@ -247,6 +268,7 @@ - name: Ensure that 'host04' has A record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: "{{ ipv4_prefix }}.104" @@ -256,6 +278,7 @@ - name: Ensure that 'host04' has A record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: "{{ ipv4_prefix }}.104" @@ -265,6 +288,7 @@ - name: Ensure that 'host04' has the same A record with reverse. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 a_rec: "{{ ipv4_prefix }}.104" @@ -275,6 +299,7 @@ - name: Ensure that 'host04' has the same A record with reverse, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 a_rec: "{{ ipv4_prefix }}.104" @@ -285,6 +310,7 @@ - name: Ensure that 'host04' has another A record with reverse. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: "{{ ipv4_prefix }}.114" @@ -294,6 +320,7 @@ - name: Ensure that 'host04' has another A record with reverse, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: "{{ ipv4_prefix }}.114" @@ -304,6 +331,7 @@ - name: Ensure that 'host04' has AAAA record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 aaaa_ip_address: fd00::0004 @@ -314,6 +342,7 @@ - name: Ensure that 'host04' has AAAA record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: fd00::0004 @@ -324,6 +353,7 @@ - name: Ensure that 'host04' has AAAA record, without reverse. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: fd00::0014 @@ -333,6 +363,7 @@ - name: Ensure that 'host04' previous AAAA record, now has a reverse record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 aaaa_rec: fd00::0014 @@ -343,6 +374,7 @@ - name: Ensure that 'host04' previous AAAA record, now has a reverse record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 aaaa_rec: fd00::0014 @@ -353,6 +385,7 @@ - name: Ensure that 'host04' has PTR record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ zone_prefix_reverse_24 }}" name: "124" ptr_hostname: "host04.{{ testzone }}" @@ -362,6 +395,7 @@ - name: Ensure that 'host04' has PTR record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ zone_prefix_reverse_24 }}" name: "124" ptr_hostname: "host04.{{ testzone }}" @@ -371,6 +405,7 @@ - name: Ensure that 'host04' has PTR record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ zone_prefix_reverse_24 }}" name: "124" ptr_rec: "host04.{{ testzone }}" @@ -381,6 +416,7 @@ - name: Ensure that 'host04' has PTR record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ zone_prefix_reverse_24 }}" name: "124" ptr_rec: "host04.{{ testzone }}" @@ -391,6 +427,7 @@ - name: Ensure that 'host04' has DNAME record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dname_target: "ipa.{{ testzone }}" @@ -400,6 +437,7 @@ - name: Ensure that 'host04' has DNAME record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dname_target: "ipa.{{ testzone }}" @@ -409,6 +447,7 @@ - name: Ensure that 'host04' DNAME record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dname_rec: "ipa.{{ testzone }}" @@ -419,6 +458,7 @@ - name: Ensure that 'host04' DNAME record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dname_rec: "ipa.{{ testzone }}" @@ -431,6 +471,7 @@ - name: Ensure that 'host04' has a A record with reverse, for NS record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ip_address: "{{ ipv4_prefix }}.114" @@ -441,6 +482,7 @@ - name: Ensure that 'host04' has NS record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ns_hostname: host04 @@ -450,6 +492,7 @@ - name: Ensure that 'host04' has NS record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ns_hostname: host04 @@ -461,6 +504,7 @@ - name: Ensure that 'host04' NS record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ns_rec: host04 @@ -471,6 +515,7 @@ - name: Ensure that 'host04' NS record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 ns_rec: host04 @@ -481,6 +526,7 @@ - name: Ensure that 'host04' DLV record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_key_tag: 12345 @@ -494,6 +540,7 @@ - name: Ensure that 'host04' DLV record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_key_tag: 12345 @@ -506,6 +553,7 @@ - name: Ensure that 'host04' DLV record is present, with a different key tag. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_key_tag: 4321 @@ -516,6 +564,7 @@ - name: Ensure that 'host04' DLV second record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_key_tag: 4321 @@ -529,6 +578,7 @@ - name: Ensure that 'host04' DLV record is changed, in presence of multiple records. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_key_tag: 54321 @@ -539,6 +589,7 @@ - name: Ensure that 'host04' DLV record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_record: 54321 3 1 08ff468cb25ccd21642989294cc33570da5eb2ba @@ -549,6 +600,7 @@ - name: Ensure that 'host04' DLV record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_record: 54321 3 1 08ff468cb25ccd21642989294cc33570da5eb2ba @@ -559,6 +611,7 @@ - name: Ensure that 'host04' DLV record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 dlv_record: 4321 2 2 da39a3ee5e6b4b0d3255bfef95601890afd80709 @@ -569,6 +622,7 @@ - name: Ensure that dns record 'iron01' is present ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: iron01 zone_name: "{{ safezone }}" ip_address: "{{ ansible_facts['default_ipv4'].address }}" @@ -578,6 +632,7 @@ - name: Ensure that NS record for "{{ safezone }}" is present ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: iron01 zone_name: "{{ safezone }}" ns_hostname: iron01 @@ -587,6 +642,7 @@ - name: Ensure that 'iron01' DS record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ safezone }}" name: iron01 ds_key_tag: 12345 @@ -600,6 +656,7 @@ - name: Ensure that 'iron01' DS record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ safezone }}" name: iron01 ds_key_tag: 12345 @@ -612,6 +669,7 @@ - name: Ensure that 'iron01' DS record is present, with a different key tag. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ safezone }}" name: iron01 ds_key_tag: 54321 @@ -622,6 +680,7 @@ - name: Ensure that 'iron01' DS record is present, with a different key tag, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ safezone }}" name: iron01 ds_key_tag: 54321 @@ -632,6 +691,7 @@ - name: Ensure that 'iron01' DS record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ safezone }}" name: iron01 ds_rec: 54321 3 1 84763786e4213cca9a6938dba5dacd64f87ec216 @@ -642,6 +702,7 @@ - name: Ensure that 'iron01' DS record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ safezone }}" name: iron01 ds_rec: 54321 3 1 84763786e4213cca9a6938dba5dacd64f87ec216 @@ -652,6 +713,7 @@ - name: Ensure that 'host04' AFSDB record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 afsdb_subtype: 1 @@ -662,6 +724,7 @@ - name: Ensure that 'host04' AFSDB record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 afsdb_subtype: 1 @@ -672,6 +735,7 @@ - name: Ensure that 'host04' AFSDB record subtype is 2. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 afsdb_subtype: 2 @@ -682,6 +746,7 @@ - name: Ensure that 'host04' AFSDB record subtype is 2, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 afsdb_subtype: 2 @@ -692,6 +757,7 @@ - name: Ensure that 'host04' AFSDB record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 afsdb_rec: "2 host04.{{ testzone }}" @@ -702,6 +768,7 @@ - name: Ensure that 'host04' AFSDB record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 afsdb_rec: "2 host04.{{ testzone }}" @@ -712,6 +779,7 @@ - name: Ensure that 'host04' CERT record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cert_type: 1 @@ -724,6 +792,7 @@ - name: Ensure that 'host04' CERT record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cert_type: 1 @@ -736,6 +805,7 @@ - name: Ensure that 'host04' CERT record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cert_rec: "1 1234 3 {{ lookup('file', 'cert1.b64') }}" @@ -746,6 +816,7 @@ - name: Ensure that 'host04' CERT record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 cert_rec: 1 1234 3 "{{ lookup('file', 'cert1.b64') }}" @@ -756,6 +827,7 @@ - name: Ensure that 'host04' KX record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_preference: 10 @@ -766,6 +838,7 @@ - name: Ensure that 'host04' KX record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_preference: 10 @@ -776,6 +849,7 @@ - name: Ensure that 'host04' KX record is present with preference set to 20. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_preference: 20 @@ -786,6 +860,7 @@ - name: Ensure that 'host04' KX record is present with preference set to 20, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_preference: 20 @@ -796,6 +871,7 @@ - name: Ensure that 'host04' KX record is present with preference set to 20, one more time. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_preference: 20 @@ -806,6 +882,7 @@ - name: Ensure that 'host04' KX record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_rec: "20 keyex.{{ testzone }}" @@ -816,6 +893,7 @@ - name: Ensure that 'host04' KX record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 kx_rec: "20 keyex.{{ testzone }}" @@ -826,6 +904,7 @@ - name: Ensure that 'host04' MX record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 mx_preference: 10 @@ -836,6 +915,7 @@ - name: Ensure that 'host04' MX record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 mx_preference: 10 @@ -846,6 +926,7 @@ - name: Ensure that 'host04' MX record is present with preference set to 20. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 mx_preference: 20 @@ -856,6 +937,7 @@ - name: Ensure that 'host04' MX record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 mx_rec: "20 mail.{{ testzone }}" @@ -866,6 +948,7 @@ - name: Ensure that 'host04' MX record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 mx_rec: "20 mail.{{ testzone }}" @@ -876,6 +959,7 @@ - name: Ensure that 'host04' LOC record is present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 loc_lat_deg: 52 @@ -896,6 +980,7 @@ - name: Ensure that 'host04' LOC record is present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 loc_lat_deg: 52 @@ -916,6 +1001,7 @@ - name: Ensure that 'host04' LOC record is present, with loc_size 1.00. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 loc_size: 1.00 @@ -926,6 +1012,7 @@ - name: Ensure that 'host04' LOC record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 loc_rec: 52 22 23.000 N 4 53 32.000 E -2.00 1.00 10000.00 10.00 @@ -936,6 +1023,7 @@ - name: Ensure that 'host04' LOC record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 loc_rec: 52 22 23.000 N 4 53 32.000 E -2.00 1.00 10000.00 10.00 @@ -946,6 +1034,7 @@ - name: Ensure that '_sip._udp' service has NAPTR record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp naptr_order: 100 @@ -960,6 +1049,7 @@ - name: Ensure that '_sip._udp' service has NAPTR record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp naptr_order: 100 @@ -974,6 +1064,7 @@ - name: Change '_sip._udp' service NAPTR record `preference` to 20. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp naptr_preference: 20 @@ -984,6 +1075,7 @@ - name: Ensure that '_sip._udp' service has NAPTR record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp naptr_order: 101 @@ -996,6 +1088,7 @@ - name: Ensure that '_sip._udp' service has NAPTR record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp naptr_order: 102 @@ -1008,6 +1101,7 @@ - name: Change '_sip._udp' service NAPTR record `preference` to 50, when multiple records are present. (BZ 1881436) ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp naptr_preference: 50 @@ -1018,6 +1112,7 @@ - name: Ensure that '_sip._udp' service has NAPTR record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp record_type: NAPTR @@ -1029,6 +1124,7 @@ - name: Ensure that '_sip._udp' service has NAPTR record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp record_type: NAPTR @@ -1040,6 +1136,7 @@ - name: Clear NAPTR records. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp del_all: yes @@ -1049,6 +1146,7 @@ - name: Ensure that '_sip._udp' service has SRV record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_priority: 10 @@ -1061,6 +1159,7 @@ - name: Ensure that '_sip._udp' service has SRV record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_priority: 10 @@ -1073,6 +1172,7 @@ - name: Ensure '_sip._udp' SRV record has priority equals to 4. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_priority: 4 @@ -1086,6 +1186,7 @@ - name: Ensure '_sip._udp' SRV record has priority equals to 4, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_priority: 4 @@ -1099,6 +1200,7 @@ - name: Ensurer '_sip._udp' SRV record has priority 2, weight 20 ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_priority: 2 @@ -1111,6 +1213,7 @@ - name: Ensurer '_sip._udp' SRV record has priority 2, weight 20, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_priority: 2 @@ -1123,6 +1226,7 @@ - name: Ensure that '_sip._udp' SRV record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_record: "2 20 5060 sip-server.{{ testzone }}" @@ -1133,6 +1237,7 @@ - name: Ensure that '_sip._udp' SRV record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _sip._udp srv_record: "2 20 5060 sip-server.{{ testzone }}" @@ -1144,6 +1249,7 @@ - name: Ensure that 'host04' has SSHFP record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 sshfp_algorithm: 1 @@ -1155,6 +1261,7 @@ - name: Ensure that 'host04' has SSHFP record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 sshfp_algorithm: 1 @@ -1166,6 +1273,7 @@ - name: Ensure that 'host04' SSHFP record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 sshfp_rec: 1 1 d21802c61733e055b8d16296cbce300efb8a167a @@ -1176,6 +1284,7 @@ - name: Ensure that 'host04' SSHFP record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 sshfp_rec: 1 1 d21802c61733e055b8d16296cbce300efb8a167a @@ -1188,6 +1297,7 @@ - name: Ensure that 'host04' has TLSA record present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 tlsa_cert_usage: 3 @@ -1200,6 +1310,7 @@ - name: Ensure that 'host04' has TLSA record present, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 tlsa_cert_usage: 3 @@ -1212,6 +1323,7 @@ - name: Modify 'host04' has TLSA record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 tlsa_matching_type: 0 @@ -1222,6 +1334,7 @@ - name: Modify 'host04' has TLSA record, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 tlsa_matching_type: 0 @@ -1232,6 +1345,7 @@ - name: Ensure that 'host04' TLSA record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 tlsa_rec: 3 1 0 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2 @@ -1242,6 +1356,7 @@ - name: Ensure that 'host04' TLSA record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 tlsa_rec: 3 1 0 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2 @@ -1252,6 +1367,7 @@ - name: Ensure that 'host04' has TXT record present. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_data: Some Text @@ -1261,6 +1377,7 @@ # - name: Ensure that 'host04' has TXT record present, again. # ipadnsrecord: # ipaadmin_password: SomeADMINpassword + # ipaapi_context: "{{ ipa_context | default(omit) }}" # zone_name: "{{ testzone }}" # name: host04 # txt_data: Some Text @@ -1270,6 +1387,7 @@ - name: Change value of 'host04' TXT record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_data: Some new Text @@ -1280,6 +1398,7 @@ - name: Add a second TXT record to 'host04'. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_rec: Some Other Text @@ -1289,6 +1408,7 @@ - name: Add a second TXT record to 'host04', again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_rec: Some Other Text @@ -1298,6 +1418,7 @@ - name: Ensure that one of 'host04' TXT record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_rec: Some new Text @@ -1308,6 +1429,7 @@ - name: Ensure that one of 'host04' TXT record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_rec: Some new Text @@ -1318,6 +1440,7 @@ - name: Ensure that 'host04' TXT record are all absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_rec: @@ -1330,6 +1453,7 @@ - name: Ensure that 'host04' TXT record are all absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: host04 txt_rec: @@ -1342,6 +1466,7 @@ - name: Ensure that '_ftp._tcp' has URI record. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_priority: 10 @@ -1353,6 +1478,7 @@ - name: Ensure that '_ftp._tcp' has URI record, again ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_priority: 10 @@ -1364,6 +1490,7 @@ - name: Change '_ftp._tcp' URI record weight to 3 and priority to 5. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_priority: 5 @@ -1375,6 +1502,7 @@ - name: Verify if modification worked. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_rec: 10 1 ftp://ftp.host04.{{ testzone }}/public @@ -1386,6 +1514,7 @@ - name: Change '_ftp._tcp' URI record weight to 3 and priority to 5, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_priority: 5 @@ -1397,6 +1526,7 @@ - name: Ensure that '_ftp._tcp' URI record is absent. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_rec: 5 3 "ftp://ftp.host04.{{ testzone }}/public" @@ -1407,6 +1537,7 @@ - name: Ensure that '_ftp._tcp' URI record is absent, again. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ testzone }}" name: _ftp._tcp uri_rec: 5 3 "ftp://ftp.host04.{{ testzone }}/public" diff --git a/tests/dnsrecord/test_dnsrecord_client_context.yml b/tests/dnsrecord/test_dnsrecord_client_context.yml new file mode 100644 index 00000000..46378492 --- /dev/null +++ b/tests/dnsrecord/test_dnsrecord_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test dnsrecord + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipadnsrecord: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test dnsrecord using client context, in client host. + import_playbook: test_dnsrecord.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test dnsrecord using client context, in server host. + import_playbook: test_dnsrecord.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From cf7b197a1f76b2b39d138d8fa517c9a2cb39d33f Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:31:57 -0300 Subject: [PATCH 11/32] ipadnszone: Allow execution of plugin in client host. Update dnszone README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/dnszone/test_dnszone_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. Due to differences in data returned when running in a client context, verification if zone is active had to be modified. --- README-dnszone.md | 1 + plugins/modules/ipadnszone.py | 2 +- tests/dnszone/env_cleanup.yml | 1 + tests/dnszone/test_dnszone.yml | 29 ++++++++++++++- tests/dnszone/test_dnszone_client_context.yml | 37 +++++++++++++++++++ 5 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 tests/dnszone/test_dnszone_client_context.yml diff --git a/README-dnszone.md b/README-dnszone.md index 308c58fe..544b86ef 100644 --- a/README-dnszone.md +++ b/README-dnszone.md @@ -202,6 +202,7 @@ 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 `name` \| `zone_name` | The zone name string or list of strings. | no `name_from_ip` | Derive zone name from reverse of IP (PTR). Can only be used with `state: present`. | no `forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py index e2b8dba1..30ceef27 100644 --- a/plugins/modules/ipadnszone.py +++ b/plugins/modules/ipadnszone.py @@ -405,7 +405,7 @@ class DNSZoneModule(FreeIPABaseModule): is_zone_active = False else: zone = response["result"] - is_zone_active = zone.get("idnszoneactive") == ["TRUE"] + is_zone_active = "TRUE" in zone.get("idnszoneactive") return zone, is_zone_active diff --git a/tests/dnszone/env_cleanup.yml b/tests/dnszone/env_cleanup.yml index 76996092..542247c3 100644 --- a/tests/dnszone/env_cleanup.yml +++ b/tests/dnszone/env_cleanup.yml @@ -2,6 +2,7 @@ - name: Ensure zone is absent. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - testzone.local - test1.testzone.local diff --git a/tests/dnszone/test_dnszone.yml b/tests/dnszone/test_dnszone.yml index 39f9cf38..b7e01d4c 100644 --- a/tests/dnszone/test_dnszone.yml +++ b/tests/dnszone/test_dnszone.yml @@ -1,6 +1,6 @@ --- - name: Test dnszone - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: true @@ -14,6 +14,7 @@ - name: Check if zone is present, when in shouldn't be. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: present check_mode: yes @@ -23,6 +24,7 @@ - name: Check if zone is present again, when in shouldn't be. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: present check_mode: yes @@ -32,6 +34,7 @@ - name: Ensure zone is present. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: present register: result @@ -40,6 +43,7 @@ - name: Check if zone is present, when in should be. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: present check_mode: yes @@ -49,6 +53,7 @@ - name: Ensure zone is present, again. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: present register: result @@ -57,6 +62,7 @@ - name: Ensure zone is disabled. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: disabled register: result @@ -65,6 +71,7 @@ - name: Ensure zone is disabled, again. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: disabled register: result @@ -73,6 +80,7 @@ - name: Ensure zone is enabled. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: enabled register: result @@ -81,6 +89,7 @@ - name: Ensure zone is enabled, again. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local state: enabled register: result @@ -89,6 +98,7 @@ - name: Ensure forward_policy is none. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forward_policy: none register: result @@ -97,6 +107,7 @@ - name: Ensure forward_policy is none, again. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forward_policy: none register: result @@ -105,6 +116,7 @@ - name: Ensure forward_policy is first. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forward_policy: first register: result @@ -113,6 +125,7 @@ - name: Ensure forward_policy is first, again. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forward_policy: first register: result @@ -121,6 +134,7 @@ - name: Ensure first forwarder is set. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forwarders: - ip_address: 8.8.8.8 @@ -131,6 +145,7 @@ - name: Ensure first and second forwarder are set. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forwarders: - ip_address: 8.8.8.8 @@ -142,6 +157,7 @@ - name: Ensure first and second forwarder are set, again. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forwarders: - ip_address: 8.8.8.8 @@ -153,6 +169,7 @@ - name: Ensure only second forwarder is set. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forwarders: - ip_address: 2001:4860:4860::8888 @@ -162,6 +179,7 @@ - name: Nothing changes. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local register: result failed_when: result.changed or result.failed @@ -169,6 +187,7 @@ - name: Ensure no forwarders are set. ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testzone.local forwarders: [] register: result @@ -177,6 +196,7 @@ - name: Create zones test1 ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test1.testzone.local register: result failed_when: not result.changed or result.failed @@ -184,6 +204,7 @@ - name: Create zones test1, again ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test1.testzone.local register: result failed_when: result.changed or result.failed @@ -191,6 +212,7 @@ - name: Create zones test2 ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test2.testzone.local register: result failed_when: not result.changed or result.failed @@ -198,6 +220,7 @@ - name: Create zones test2, again ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test2.testzone.local register: result failed_when: result.changed or result.failed @@ -205,6 +228,7 @@ - name: Create zones test3 ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test3.testzone.local register: result failed_when: not result.changed or result.failed @@ -212,6 +236,7 @@ - name: Create zones test3, again ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test3.testzone.local register: result failed_when: result.changed or result.failed @@ -219,6 +244,7 @@ - name: Ensure multiple zones are absent ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - test1.testzone.local - test2.testzone.local @@ -230,6 +256,7 @@ - name: Ensure multiple zones are absent, again ipadnszone: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - test1.testzone.local - test2.testzone.local diff --git a/tests/dnszone/test_dnszone_client_context.yml b/tests/dnszone/test_dnszone_client_context.yml new file mode 100644 index 00000000..0f7f959a --- /dev/null +++ b/tests/dnszone/test_dnszone_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test dnszone + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipadnszone: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test dnszone using client context, in client host. + import_playbook: test_dnszone.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test dnszone using client context, in server host. + import_playbook: test_dnszone.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 1fdf7a43590bd3d837f97429908e48da1a61a14b Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:18 -0300 Subject: [PATCH 12/32] ipagroup: Allow execution of plugin in client host. Update group README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/group/test_group_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-group.md | 1 + tests/group/test_group.yml | 22 ++++++++++++-- tests/group/test_group_client_context.yml | 37 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/group/test_group_client_context.yml diff --git a/README-group.md b/README-group.md index f845ef05..662fcd01 100644 --- a/README-group.md +++ b/README-group.md @@ -154,6 +154,7 @@ 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 `name` \| `cn` | The list of group name strings. | no `description` | The group description string. | no `gid` \| `gidnumber` | The GID integer. | no diff --git a/tests/group/test_group.yml b/tests/group/test_group.yml index 855443bd..74b170c5 100644 --- a/tests/group/test_group.yml +++ b/tests/group/test_group.yml @@ -1,6 +1,6 @@ --- - name: Test group - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,18 +8,21 @@ - name: Ensure users user1, user2 and user3 are absent ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: user1,user2,user3 state: absent - name: Ensure group group3, group2 and group1 are absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group3,group2,group1 state: absent - name: Ensure users user1..user3 are present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" users: - name: user1 first: user1 @@ -36,6 +39,7 @@ - name: Ensure group1 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 register: result failed_when: not result.changed or result.failed @@ -43,6 +47,7 @@ - name: Ensure group1 is present again ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 register: result failed_when: result.changed or result.failed @@ -50,6 +55,7 @@ - name: Ensure group2 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group2 register: result failed_when: not result.changed or result.failed @@ -57,6 +63,7 @@ - name: Ensure group2 is present again ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group2 register: result failed_when: result.changed or result.failed @@ -64,6 +71,7 @@ - name: Ensure group3 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group3 register: result failed_when: not result.changed or result.failed @@ -71,6 +79,7 @@ - name: Ensure group3 is present again ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group3 register: result failed_when: result.changed or result.failed @@ -78,6 +87,7 @@ - name: Ensure groups group2 and group3 are present in group group1 ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 group: - group2 @@ -89,6 +99,7 @@ - name: Ensure groups group2 and group3 are present in group group1 again ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 group: - group2 @@ -100,6 +111,7 @@ - name: Ensure group3 ia present in group group1 ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 group: - group3 @@ -110,6 +122,7 @@ - name: Ensure users user1, user2 and user3 are present in group group1 ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 user: - user1 @@ -122,6 +135,7 @@ - name: Ensure users user1, user2 and user3 are present in group group1 again ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 user: - user1 @@ -133,6 +147,7 @@ #- ipagroup: # ipaadmin_password: SomeADMINpassword + # ipaapi_context: "{{ ipa_context | default(omit) }}" # name: group1 # user: # - user7 @@ -141,6 +156,7 @@ - name: Ensure user user7 is absent in group group1 ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group1 user: - user7 @@ -152,6 +168,7 @@ - name: Ensure group group4 is absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group4 state: absent register: result @@ -160,6 +177,7 @@ - name: Ensure group group3, group2 and group1 are absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group3,group2,group1 state: absent register: result @@ -168,8 +186,8 @@ - name: Ensure users user1, user2 and user3 are absent ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: user1,user2,user3 state: absent register: result failed_when: not result.changed or result.failed - diff --git a/tests/group/test_group_client_context.yml b/tests/group/test_group_client_context.yml new file mode 100644 index 00000000..5e58cbfd --- /dev/null +++ b/tests/group/test_group_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test group + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipagroup: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test group using client context, in client host. + import_playbook: test_group.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test group using client context, in server host. + import_playbook: test_group.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 876187ab85f9522f16d365bdcaa4d8153d7b9a88 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:20 -0300 Subject: [PATCH 13/32] ipahbacrule: Allow execution of plugin in client host. Update hbacrule README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/hbacrule/test_hbacrule_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-hbacrule.md | 1 + tests/hbacrule/test_hbacrule.yml | 69 ++++++++++++++++++- .../hbacrule/test_hbacrule_client_context.yml | 37 ++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/hbacrule/test_hbacrule_client_context.yml diff --git a/README-hbacrule.md b/README-hbacrule.md index a1b69877..fee62820 100644 --- a/README-hbacrule.md +++ b/README-hbacrule.md @@ -136,6 +136,7 @@ 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 `name` \| `cn` | The list of hbacrule name strings. | yes `description` | The hbacrule description string. | no `usercategory` \| `usercat` | User category the rule applies to. Choices: ["all", ""] | no diff --git a/tests/hbacrule/test_hbacrule.yml b/tests/hbacrule/test_hbacrule.yml index e93a74dc..0c161644 100644 --- a/tests/hbacrule/test_hbacrule.yml +++ b/tests/hbacrule/test_hbacrule.yml @@ -1,6 +1,6 @@ --- - name: Test hbacrule - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -14,6 +14,7 @@ - name: Ensure test hosts are absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ 'testhost01.' + ipaserver_domain }}" - "{{ 'testhost02.' + ipaserver_domain }}" @@ -24,30 +25,35 @@ - name: Ensure test hostgroups are absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04 state: absent - name: Ensure test users are absent ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testuser01,testuser02,testuser03,testuser04 state: absent - name: Ensure test user groups are absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup01,testgroup02,testgroup03,testgroup04 state: absent - name: Ensure test HBAC Services are absent ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04 state: absent - name: Ensure test HBAC Service Groups are absent ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04 state: absent @@ -56,6 +62,7 @@ - name: Ensure hosts "{{ 'host[1..4].' + ipaserver_domain }}" are present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" hosts: - name: "{{ 'testhost01.' + ipaserver_domain }}" force: yes @@ -71,6 +78,7 @@ - name: Ensure host-group testhostgroup01 is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup01 register: result failed_when: not result.changed or result.failed @@ -78,6 +86,7 @@ - name: Ensure host-group testhostgroup02 is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup02 register: result failed_when: not result.changed or result.failed @@ -85,6 +94,7 @@ - name: Ensure host-group testhostgroup03 is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup03 register: result failed_when: not result.changed or result.failed @@ -92,6 +102,7 @@ - name: Ensure host-group testhostgroup04 is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup04 register: result failed_when: not result.changed or result.failed @@ -99,6 +110,7 @@ - name: Ensure testusers are present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" users: - name: testuser01 first: test @@ -118,6 +130,7 @@ - name: Ensure user group testgroup01 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup01 register: result failed_when: not result.changed or result.failed @@ -125,6 +138,7 @@ - name: Ensure user group testgroup02 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup02 register: result failed_when: not result.changed or result.failed @@ -132,6 +146,7 @@ - name: Ensure user group testgroup03 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup03 register: result failed_when: not result.changed or result.failed @@ -139,6 +154,7 @@ - name: Ensure user group testgroup04 is present ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup04 register: result failed_when: not result.changed or result.failed @@ -146,6 +162,7 @@ - name: Ensure HBAC Service testhbacsvc01 is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvc01 register: result failed_when: not result.changed or result.failed @@ -153,6 +170,7 @@ - name: Ensure HBAC Service testhbacsvc02 is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvc02 register: result failed_when: not result.changed or result.failed @@ -160,6 +178,7 @@ - name: Ensure HBAC Service testhbacsvc03 is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvc03 register: result failed_when: not result.changed or result.failed @@ -167,6 +186,7 @@ - name: Ensure HBAC Service testhbacsvc04 is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvc04 register: result failed_when: not result.changed or result.failed @@ -174,6 +194,7 @@ - name: Ensure HBAC Service Group testhbacsvcgroup01 is present ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvcgroup01 register: result failed_when: not result.changed or result.failed @@ -181,6 +202,7 @@ - name: Ensure HBAC Service Group testhbacsvcgroup02 is present ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvcgroup02 register: result failed_when: not result.changed or result.failed @@ -188,6 +210,7 @@ - name: Ensure HBAC Service Group testhbacsvcgroup03 is present ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvcgroup03 register: result failed_when: not result.changed or result.failed @@ -195,6 +218,7 @@ - name: Ensure HBAC Service Group testhbacsvcgroup04 is present ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvcgroup04 register: result failed_when: not result.changed or result.failed @@ -202,6 +226,7 @@ - name: Ensure test HBAC rule hbacrule01 is absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 state: absent @@ -210,6 +235,7 @@ - name: Ensure HBAC rule hbacrule01 is present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 register: result failed_when: not result.changed or result.failed @@ -217,6 +243,7 @@ - name: Ensure HBAC rule hbacrule01 is present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 register: result failed_when: result.changed or result.failed @@ -226,6 +253,7 @@ - name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -241,6 +269,7 @@ - name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -258,6 +287,7 @@ - name: Ensure test HBAC rule hbacrule01 host members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -270,6 +300,7 @@ - name: Ensure test HBAC rule hbacrule01 host members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -282,6 +313,7 @@ - name: Ensure test HBAC rule hbacrule01 hostgroup members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hostgroup: testhostgroup01,testhostgroup02 state: absent @@ -292,6 +324,7 @@ - name: Ensure test HBAC rule hbacrule01 hostgroup members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hostgroup: testhostgroup01,testhostgroup02 state: absent @@ -302,6 +335,7 @@ - name: Ensure test HBAC rule hbacrule01 user members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 user: testuser01,testuser02 state: absent @@ -312,6 +346,7 @@ - name: Ensure test HBAC rule hbacrule01 user members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 user: testuser01,testuser02 state: absent @@ -322,6 +357,7 @@ - name: Ensure test HBAC rule hbacrule01 user group members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 group: testgroup01,testgroup02 state: absent @@ -332,6 +368,7 @@ - name: Ensure test HBAC rule hbacrule01 user group members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 group: testgroup01,testgroup02 state: absent @@ -342,6 +379,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvc: testhbacsvc01,testhbacsvc02 state: absent @@ -352,6 +390,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvc: testhbacsvc01,testhbacsvc02 state: absent @@ -362,6 +401,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 state: absent @@ -372,6 +412,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 state: absent @@ -384,6 +425,7 @@ - name: Ensure test HBAC rule hbacrule01 host members are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -395,6 +437,7 @@ - name: Ensure test HBAC rule hbacrule01 host members are present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -406,6 +449,7 @@ - name: Ensure test HBAC rule hbacrule01 hostgroup members are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hostgroup: testhostgroup01,testhostgroup02 action: member @@ -415,6 +459,7 @@ - name: Ensure test HBAC rule hbacrule01 hostgroup members are present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hostgroup: testhostgroup01,testhostgroup02 action: member @@ -424,6 +469,7 @@ - name: Ensure test HBAC rule hbacrule01 user members are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 user: testuser01,testuser02 action: member @@ -433,6 +479,7 @@ - name: Ensure test HBAC rule hbacrule01 user members are present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 user: testuser01,testuser02 action: member @@ -442,6 +489,7 @@ - name: Ensure test HBAC rule hbacrule01 user group members are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 group: testgroup01,testgroup02 action: member @@ -451,6 +499,7 @@ - name: Ensure test HBAC rule hbacrule01 user group members are present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 group: testgroup01,testgroup02 action: member @@ -460,6 +509,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvc: testhbacsvc01,testhbacsvc02 action: member @@ -469,6 +519,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvc: testhbacsvc01,testhbacsvc02 action: member @@ -478,6 +529,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 action: member @@ -487,6 +539,7 @@ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 action: member @@ -498,6 +551,7 @@ - name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost03.' + ipaserver_domain }}" @@ -513,6 +567,7 @@ - name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost03.' + ipaserver_domain }}" @@ -530,6 +585,7 @@ - name: Ensure HBAC rule hbacrule01 members (same) are present ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost01.' + ipaserver_domain }}" @@ -549,6 +605,7 @@ - name: Ensure HBAC rule hbacrule01 members are absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost03.' + ipaserver_domain }}" @@ -566,6 +623,7 @@ - name: Ensure HBAC rule hbacrule01 members are absent again ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "{{ 'testhost03.' + ipaserver_domain }}" @@ -585,6 +643,7 @@ - name: Ensure HBAC rule hbacrule01 simple host members are usable ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "testhost01" @@ -595,6 +654,7 @@ - name: Ensure HBAC rule hbacrule01 simple host members are usable again (and match) ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 host: - "testhost01" @@ -607,12 +667,14 @@ - name: Ensure test HBAC rule hbacrule01 is absent ipahbacrule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hbacrule01 state: absent - name: Ensure test hosts are absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ 'testhost01.' + ipaserver_domain }}" - "{{ 'testhost02.' + ipaserver_domain }}" @@ -623,29 +685,34 @@ - name: Ensure test hostgroups are absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04 state: absent - name: Ensure test users are absent ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testuser01,testuser02,testuser03,testuser04 state: absent - name: Ensure test user groups are absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testgroup01,testgroup02,testgroup03,testgroup04 state: absent - name: Ensure test HBAC Services are absent ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04 state: absent - name: Ensure test HBAC Service Groups are absent ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04 state: absent diff --git a/tests/hbacrule/test_hbacrule_client_context.yml b/tests/hbacrule/test_hbacrule_client_context.yml new file mode 100644 index 00000000..efa3fa9c --- /dev/null +++ b/tests/hbacrule/test_hbacrule_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test hbacrule + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipahbacrule: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test hbacrule using client context, in client host. + import_playbook: test_hbacrule.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test hbacrule using client context, in server host. + import_playbook: test_hbacrule.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From ec777dab8fabd7595e562a2d91d0409e624bb9d7 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:23 -0300 Subject: [PATCH 14/32] ipahbacsvc: Allow execution of plugin in client host. Update hbacsvc README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/hbacsvc/test_hbacsvc_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-hbacsvc.md | 1 + tests/hbacsvc/test_hbacsvc.yml | 9 ++++- tests/hbacsvc/test_hbacsvc_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/hbacsvc/test_hbacsvc_client_context.yml diff --git a/README-hbacsvc.md b/README-hbacsvc.md index 7203e549..49644b8f 100644 --- a/README-hbacsvc.md +++ b/README-hbacsvc.md @@ -98,6 +98,7 @@ 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 `name` \| `cn` \| `service` | The list of hbacsvc name strings. | no `description` | The hbacsvc description string. | no `state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no diff --git a/tests/hbacsvc/test_hbacsvc.yml b/tests/hbacsvc/test_hbacsvc.yml index c91cf39b..135fd11f 100644 --- a/tests/hbacsvc/test_hbacsvc.yml +++ b/tests/hbacsvc/test_hbacsvc.yml @@ -1,6 +1,6 @@ --- - name: Test hbacsvc - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,12 +8,14 @@ - name: Ensure HBAC Service for http is absent ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: http,tftp state: absent - name: Ensure HBAC Service for http is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: http register: result failed_when: not result.changed or result.failed @@ -21,6 +23,7 @@ - name: Ensure HBAC Service for http is present again ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: http register: result failed_when: result.changed or result.failed @@ -28,6 +31,7 @@ - name: Ensure HBAC Service for tftp is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: tftp description: TFTP service register: result @@ -36,6 +40,7 @@ - name: Ensure HBAC Service for tftp is present again ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: tftp description: TFTP service register: result @@ -44,6 +49,7 @@ - name: Ensure HBAC Services for http and tftp are absent ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: http,tftp state: absent register: result @@ -52,6 +58,7 @@ - name: Ensure HBAC Services for http and tftp are absent again ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: http,tftp state: absent register: result diff --git a/tests/hbacsvc/test_hbacsvc_client_context.yml b/tests/hbacsvc/test_hbacsvc_client_context.yml new file mode 100644 index 00000000..161fa022 --- /dev/null +++ b/tests/hbacsvc/test_hbacsvc_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test hbacsvc + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipahbacsvc: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test hbacsvc using client context, in client host. + import_playbook: test_hbacsvc.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test hbacsvc using client context, in server host. + import_playbook: test_hbacsvc.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 6ce1055bac021fd379a5db4d166a9142a326fa1d Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:25 -0300 Subject: [PATCH 15/32] ipahbacsvcgroup: Allow execution of plugin in client host. Update hbacsvcgroup README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-hbacsvcgroup.md | 1 + tests/hbacsvcgroup/test_hbacsvcgroup.yml | 12 +++++- .../test_hbacsvcgroup_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml diff --git a/README-hbacsvcgroup.md b/README-hbacsvcgroup.md index 56d5f7a6..c2beae41 100644 --- a/README-hbacsvcgroup.md +++ b/README-hbacsvcgroup.md @@ -136,6 +136,7 @@ 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 `name` \| `cn` | The list of hbacsvcgroup name strings. | no `description` | The hbacsvcgroup description string. | no `nomembers` | Suppress processing of membership attributes. (bool) | no diff --git a/tests/hbacsvcgroup/test_hbacsvcgroup.yml b/tests/hbacsvcgroup/test_hbacsvcgroup.yml index d0cd02cd..024b3904 100644 --- a/tests/hbacsvcgroup/test_hbacsvcgroup.yml +++ b/tests/hbacsvcgroup/test_hbacsvcgroup.yml @@ -1,6 +1,6 @@ --- - name: Test hbacsvcgroup - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,17 +8,20 @@ - name: Ensure HBAC Service Group login is absent ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login state: absent - name: Ensure HBAC Service for sshd is present ipahbacsvc: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login - name: Ensure HBAC Service Group login is present ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login register: result failed_when: not result.changed or result.failed @@ -26,6 +29,7 @@ - name: Ensure HBAC Service Group login is present again ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login register: result failed_when: result.changed or result.failed @@ -33,6 +37,7 @@ - name: Ensure HBAC Service sshd is present in HBAC Service Group login ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login hbacsvc: - sshd @@ -43,6 +48,7 @@ - name: Ensure HBAC Service sshd is present in HBAC Service Group login again ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login hbacsvc: - sshd @@ -53,6 +59,7 @@ - name: Ensure HBAC Services sshd and foo are absent in HBAC Service Group login ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login hbacsvc: - sshd @@ -65,6 +72,7 @@ - name: Ensure HBAC Services sshd and foo are absent in HBAC Service Group login again ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login hbacsvc: - sshd @@ -77,6 +85,7 @@ - name: Ensure HBAC Service Group login is absent ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login state: absent register: result @@ -85,6 +94,7 @@ - name: Ensure HBAC Service Group login is absent again ipahbacsvcgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: login state: absent register: result diff --git a/tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml b/tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml new file mode 100644 index 00000000..569fe5b4 --- /dev/null +++ b/tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test hbacsvcgroup + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipahbacsvcgroup: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test hbacsvcgroup using client context, in client host. + import_playbook: test_hbacsvcgroup.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test hbacsvcgroup using client context, in server host. + import_playbook: test_hbacsvcgroup.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From d0287f90cd078a01c518dc7a2bbd65b1754fb405 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:28 -0300 Subject: [PATCH 16/32] ipahost: Allow execution of plugin in client host. Update host README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/host/test_host_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-host.md | 1 + tests/host/test_host.yml | 20 +++++++++++-- tests/host/test_host_client_context.yml | 37 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/host/test_host_client_context.yml diff --git a/README-host.md b/README-host.md index 56c92bda..ba274c98 100644 --- a/README-host.md +++ b/README-host.md @@ -320,6 +320,7 @@ 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 `name` \| `fqdn` | The list of host name strings. `name` with *host variables* or `hosts` containing *host variables* need to be used. | no **Host variables** | Only used with `name` variable in the first level. | no `hosts` | The list of host dicts. Each `hosts` dict entry can contain **host variables**.
There is one required option in the `hosts` dict:| no diff --git a/tests/host/test_host.yml b/tests/host/test_host.yml index 3b186525..bee85ef7 100644 --- a/tests/host/test_host.yml +++ b/tests/host/test_host.yml @@ -1,6 +1,6 @@ --- - name: Test host - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -21,6 +21,7 @@ - name: Host absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ host1_fqdn }}" - "{{ host2_fqdn }}" @@ -39,6 +40,7 @@ - name: Host "{{ host1_fqdn }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host1_fqdn }}" ip_address: "{{ ipv4_prefix + '.201' }}" update_dns: yes @@ -49,6 +51,7 @@ - name: Host "{{ host1_fqdn }}" present again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host1_fqdn }}" ip_address: "{{ ipv4_prefix + '.201' }}" update_dns: yes @@ -59,6 +62,7 @@ - name: Host "{{ host2_fqdn }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host2_fqdn }}" ip_address: "{{ ipv4_prefix + '.202' }}" update_dns: yes @@ -69,6 +73,7 @@ - name: Host "{{ host2_fqdn }}" present again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host2_fqdn }}" ip_address: "{{ ipv4_prefix + '.202' }}" update_dns: yes @@ -79,6 +84,7 @@ - name: Host "{{ host3_fqdn }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host3_fqdn }}" ip_address: "{{ ipv4_prefix + '.203' }}" update_dns: yes @@ -89,6 +95,7 @@ - name: Host "{{ host3_fqdn }}" present again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host3_fqdn }}" ip_address: "{{ ipv4_prefix + '.203' }}" update_dns: yes @@ -99,6 +106,7 @@ - name: Host "{{ host4_fqdn }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host4_fqdn }}" ip_address: "{{ ipv4_prefix + '.204' }}" update_dns: yes @@ -109,6 +117,7 @@ - name: Host "{{ host4_fqdn }}" present again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host4_fqdn }}" ip_address: "{{ ipv4_prefix + '.204' }}" update_dns: yes @@ -119,6 +128,7 @@ - name: Host "{{ host5_fqdn }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host5_fqdn }}" ip_address: "{{ ipv4_prefix + '.205' }}" update_dns: yes @@ -129,6 +139,7 @@ - name: Host "{{ host5_fqdn }}" present again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host5_fqdn }}" ip_address: "{{ ipv4_prefix + '.205' }}" update_dns: yes @@ -139,6 +150,7 @@ - name: Host "{{ host6_fqdn }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host6_fqdn }}" ip_address: "{{ ipv4_prefix + '.206' }}" update_dns: yes @@ -149,6 +161,7 @@ - name: Host "{{ host6_fqdn }}" present again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host6_fqdn }}" ip_address: "{{ ipv4_prefix + '.206' }}" update_dns: yes @@ -161,6 +174,7 @@ #- name: Hosts host1..host6 disabled # ipahost: # ipaadmin_password: SomeADMINpassword + # ipaapi_context: "{{ ipa_context | default(omit) }}" # name: # - "{{ host1_fqdn }}" # - "{{ host2_fqdn }}" @@ -175,6 +189,7 @@ #- name: Hosts host1..host6 disabled again # ipahost: # ipaadmin_password: SomeADMINpassword + # ipaapi_context: "{{ ipa_context | default(omit) }}" # name: # - "{{ host1_fqdn }}" # - "{{ host2_fqdn }}" @@ -189,6 +204,7 @@ - name: Hosts host1..host6 absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ host1_fqdn }}" - "{{ host2_fqdn }}" @@ -204,6 +220,7 @@ - name: Hosts host1..host6 absent again ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ host1_fqdn }}" - "{{ host2_fqdn }}" @@ -215,4 +232,3 @@ state: absent register: result failed_when: result.changed or result.failed - diff --git a/tests/host/test_host_client_context.yml b/tests/host/test_host_client_context.yml new file mode 100644 index 00000000..ba307401 --- /dev/null +++ b/tests/host/test_host_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test host + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipahost: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test automember using client context, in client host. + import_playbook: test_host.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test automember using client context, in server host. + import_playbook: test_host.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 40f544bab440b27952ab6576f4d23ebf8eae4384 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:30 -0300 Subject: [PATCH 17/32] ipahostgroup: Allow execution of plugin in client host. Update hostgroup README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/hostgroup/test_hostgroup_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-hostgroup.md | 1 + tests/hostgroup/test_hostgroup.yml | 20 +++++++++- .../test_hostgroup_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/hostgroup/test_hostgroup_client_context.yml diff --git a/README-hostgroup.md b/README-hostgroup.md index cedca7e2..e97136ca 100644 --- a/README-hostgroup.md +++ b/README-hostgroup.md @@ -150,6 +150,7 @@ 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 `name` \| `cn` | The list of hostgroup name strings. | no `description` | The hostgroup description string. | no `nomembers` | Suppress processing of membership attributes. (bool) | no diff --git a/tests/hostgroup/test_hostgroup.yml b/tests/hostgroup/test_hostgroup.yml index 1b1ba7a6..076f76d1 100644 --- a/tests/hostgroup/test_hostgroup.yml +++ b/tests/hostgroup/test_hostgroup.yml @@ -1,6 +1,6 @@ --- - name: Test hostgroup - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: true @@ -13,6 +13,7 @@ - name: Ensure host-group databases, mysql-server and oracle-server are absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - databases - mysql-server @@ -22,6 +23,7 @@ - name: Test hosts db1 and db2 absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ 'db1.' + ipaserver_domain }}" - "{{ 'db2.' + ipaserver_domain }}" @@ -30,6 +32,7 @@ - name: Host "{{ 'db1.' + ipaserver_domain }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ 'db1.' + ipaserver_domain }}" force: yes register: result @@ -38,6 +41,7 @@ - name: Host "{{ 'db2.' + ipaserver_domain }}" present ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ 'db2.' + ipaserver_domain }}" force: yes register: result @@ -46,6 +50,7 @@ - name: Ensure host-group mysql-server is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: mysql-server state: present register: result @@ -54,6 +59,7 @@ - name: Ensure host-group mysql-server is present again ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: mysql-server state: present register: result @@ -62,6 +68,7 @@ - name: Ensure host-group oracle-server is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: oracle-server state: present register: result @@ -70,6 +77,7 @@ - name: Ensure host-group oracle-server is present again ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: oracle-server state: present register: result @@ -78,6 +86,7 @@ - name: Ensure host-group databases is present ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present host: @@ -90,6 +99,7 @@ - name: Ensure host-group databases is present again ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present host: @@ -102,6 +112,7 @@ - name: Ensure host db2 is member of host-group databases ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present host: @@ -113,6 +124,7 @@ - name: Ensure host db2 is member of host-group databases again ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present host: @@ -124,6 +136,7 @@ - name: Ensure host-group mysql-server is member of host-group databases ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present hostgroup: @@ -135,6 +148,7 @@ - name: Ensure host-group mysql-server is member of host-group databases again ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present hostgroup: @@ -146,6 +160,7 @@ - name: Ensure host-group oracle-server is member of host-group databases (again) ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: databases state: present hostgroup: @@ -157,6 +172,7 @@ - name: Ensure host-group databases, mysql-server and oracle-server are absent ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - databases - mysql-server @@ -168,6 +184,7 @@ - name: Ensure host-group databases, mysql-server and oracle-server are absent again ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - databases - mysql-server @@ -179,6 +196,7 @@ - name: Test hosts db1 and db2 absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ 'db1.' + ipaserver_domain }}" - "{{ 'db2.' + ipaserver_domain }}" diff --git a/tests/hostgroup/test_hostgroup_client_context.yml b/tests/hostgroup/test_hostgroup_client_context.yml new file mode 100644 index 00000000..a234da90 --- /dev/null +++ b/tests/hostgroup/test_hostgroup_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test hostgroup + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipahostgroup: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test hostgroup using client context, in client host. + import_playbook: test_hostgroup.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test hostgroup using client context, in server host. + import_playbook: test_hostgroup.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 1440fb39b2a7ccaa6e3d5975a0c759ef7f639490 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:33 -0300 Subject: [PATCH 18/32] ipalocation: Allow execution of plugin in client host. Update location README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/location/test_location_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-location.md | 1 + tests/location/test_location.yml | 10 ++++- .../location/test_location_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/location/test_location_client_context.yml diff --git a/README-location.md b/README-location.md index 3e9b7ef1..203ba254 100644 --- a/README-location.md +++ b/README-location.md @@ -81,6 +81,7 @@ 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 `name` \| `idnsname` | The list of location name strings. | yes `description` | The IPA location string | false `state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no diff --git a/tests/location/test_location.yml b/tests/location/test_location.yml index 10aed32f..3cda4115 100644 --- a/tests/location/test_location.yml +++ b/tests/location/test_location.yml @@ -1,6 +1,6 @@ --- - name: Test location - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -10,6 +10,7 @@ - name: Ensure location my_location1 is absent ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 state: absent @@ -20,6 +21,7 @@ - name: Ensure location my_location1 is present ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 register: result failed_when: not result.changed or result.failed @@ -27,6 +29,7 @@ - name: Ensure location my_location1 is present again ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 register: result failed_when: result.changed or result.failed @@ -34,6 +37,7 @@ - name: Ensure location my_location1 is present with description ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 description: My Location 1 register: result @@ -42,6 +46,7 @@ - name: Ensure location my_location1 is present again with description ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 description: My Location 1 register: result @@ -50,6 +55,7 @@ - name: Ensure location my_location1 is absent ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 state: absent register: result @@ -58,6 +64,7 @@ - name: Ensure location my_location1 is absent again ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 state: absent register: result @@ -68,5 +75,6 @@ - name: Ensure location my_location1 is absent ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: my_location1 state: absent diff --git a/tests/location/test_location_client_context.yml b/tests/location/test_location_client_context.yml new file mode 100644 index 00000000..00d5749f --- /dev/null +++ b/tests/location/test_location_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test location + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipalocation: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test location using client context, in client host. + import_playbook: test_location.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test location using client context, in server host. + import_playbook: test_location.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From a599f4ad87a184b0030b29911f44e831d4c5c18c Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:35 -0300 Subject: [PATCH 19/32] ipapermission: Allow execution of plugin in client host. Update permission README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/permission/test_permission_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. Due to differences in data returned when running in a client context, some values had to be modified so that comparision works and an unnecessary call to IPA API is executed. --- README-permission.md | 1 + plugins/modules/ipapermission.py | 4 ++ tests/permission/test_permission.yml | 38 ++++++++++++++++++- .../test_permission_client_context.yml | 37 ++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tests/permission/test_permission_client_context.yml diff --git a/README-permission.md b/README-permission.md index c1cc539a..950e6ff0 100644 --- a/README-permission.md +++ b/README-permission.md @@ -161,6 +161,7 @@ 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 `name` \| `cn` | The permission name string. | yes `right` \| `ipapermright` | Rights to grant. It can be a list of one or more of `read`, `search`, `compare`, `write`, `add`, `delete`, and `all` default: `all` | no `attrs` | All attributes to which the permission applies. | no diff --git a/plugins/modules/ipapermission.py b/plugins/modules/ipapermission.py index 2dc6ab1c..657d934f 100644 --- a/plugins/modules/ipapermission.py +++ b/plugins/modules/ipapermission.py @@ -371,6 +371,10 @@ def main(): for _member, _member_change in check_members.items(): if _member_change is not None: _res_list = res_find[_member] + # if running in a client context, data may be + # returned as a tuple instead of a list. + if isinstance(_res_list, tuple): + _res_list = list(_res_list) _new_set = set(_res_list + _member_change) if _new_set != set(_res_list): member_attrs[_member] = list(_new_set) diff --git a/tests/permission/test_permission.yml b/tests/permission/test_permission.yml index b4c04fcd..d7edc102 100644 --- a/tests/permission/test_permission.yml +++ b/tests/permission/test_permission.yml @@ -1,6 +1,6 @@ --- - name: Test permission - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -9,6 +9,7 @@ - name: Ensure testing groups are present. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item }}" state: present with_items: @@ -20,6 +21,7 @@ - name: Ensure permission perm-test-1 is absent ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - perm-test-1 - perm-test-bindtype-test @@ -31,6 +33,7 @@ - name: Ensure permission perm-test-1 is present ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 object_type: host memberof: rbacgroup1 @@ -42,6 +45,7 @@ - name: Ensure permission perm-test-1 is present again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 object_type: host memberof: rbacgroup1 @@ -53,6 +57,7 @@ - name: Ensure permission perm-test-1 has an extra filter '(cn=*.internal.*)' ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 filter: '(cn=*.internal.*)' action: member @@ -62,6 +67,7 @@ - name: Ensure permission perm-test-1 has an extra filter '(cn=*.internal.*)', again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 filter: '(cn=*.internal.*)' action: member @@ -71,6 +77,7 @@ - name: Ensure permission perm-test-1 `right` has `write` ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 right: write action: member @@ -80,6 +87,7 @@ - name: Ensure permission perm-test-1 `right` has `write`, again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 right: write action: member @@ -89,6 +97,7 @@ - name: Ensure permission perm-test-1 `right` has no `write` ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 right: write action: member @@ -99,6 +108,7 @@ - name: Ensure permission perm-test-1 `right` has no `write`, again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 right: write action: member @@ -109,6 +119,7 @@ - name: Ensure permission perm-test-1 `memberof` has `rbackgroup2` ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 memberof: rbacgroup2 action: member @@ -118,6 +129,7 @@ - name: Ensure permission perm-test-1 `memberof` has `rbackgroup2`, again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 memberof: rbacgroup2 action: member @@ -127,6 +139,7 @@ - name: Ensure permission perm-test-1 `memberof` item `rbackgroup1` is absent ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 memberof: rbacgroup1 action: member @@ -137,6 +150,7 @@ - name: Ensure permission perm-test-1 `memberof` item `rbackgroup1` is absent, again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 memberof: rbacgroup1 action: member @@ -147,6 +161,7 @@ - name: Ensure permission perm-test-1 is present with attr carlicense ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - carlicense @@ -156,6 +171,7 @@ - name: Ensure permission perm-test-1 is present with attr carlicense again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - carlicense @@ -165,6 +181,7 @@ - name: Ensure permission perm-test-1 is present with attr carlicense and displayname ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - carlicense @@ -175,6 +192,7 @@ - name: Ensure permission perm-test-1 is present with attr carlicense and displayname again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - carlicense @@ -185,6 +203,7 @@ - name: Ensure attr gecos is present in permission perm-test-1 ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - gecos @@ -195,6 +214,7 @@ - name: Ensure attr gecos is present in permission perm-test-1 again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - gecos @@ -205,6 +225,7 @@ - name: Ensure attr gecos is absent in permission perm-test-1 ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - gecos @@ -216,6 +237,7 @@ - name: Ensure attr gecos is absent in permission perm-test-1 again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 attrs: - gecos @@ -227,6 +249,7 @@ - name: Ensure attributes carlicense and displayname are present in permission "System{{':'}} Update DNS Entries" ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "System: Update DNS Entries" attrs: - carlicense @@ -238,6 +261,7 @@ - name: Ensure attributes carlicense and displayname are present in permission "System{{':'}} Update DNS Entries" again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "System: Update DNS Entries" attrs: - carlicense @@ -249,6 +273,7 @@ - name: Ensure attributes carlicense and displayname are present in permission "System{{':'}} Update DNS Entries" ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "System: Update DNS Entries" attrs: - carlicense @@ -261,6 +286,7 @@ - name: Ensure attributes carlicense and displayname are present in permission "System{{':'}} Update DNS Entries" again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "System: Update DNS Entries" attrs: - carlicense @@ -273,6 +299,7 @@ - name: Ensure permission perm-test-1 has rawfilter '(objectclass=ipagroup)' ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 rawfilter: '(objectclass=ipagroup)' action: member @@ -282,6 +309,7 @@ - name: Ensure permission perm-test-1 has rawfilter '(objectclass=ipagroup)', again ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 rawfilter: '(objectclass=ipagroup)' action: member @@ -291,6 +319,7 @@ - name: Ensure filter and rawfilter cannot be used together. ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 rawfilter: '(objectclass=ipagroup)' filter: '(cn=*.internal.*)' @@ -301,6 +330,7 @@ - name: Rename permission perm-test-1 to perm-test-renamed ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 rename: perm-test-renamed state: renamed @@ -310,6 +340,7 @@ - name: Ensure permission perm-test-1 is absent ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-1 state: absent register: result @@ -318,6 +349,7 @@ - name: Ensure permission perm-test-renamed is present ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-renamed object_type: host right: all @@ -327,6 +359,7 @@ - name: Ensure permission with bindtype 'self' is present, if IPA version >= 4.8.7 ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-bindtype-test bindtype: self object_type: host @@ -338,6 +371,7 @@ - name: Fail to set permission perm-test-renamed bindtype to 'self', if IPA version < 4.8.7 ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: perm-test-bindtype-test bindtype: self object_type: host @@ -351,6 +385,7 @@ - name: Ensure testing permissions are absent ipapermission: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - perm-test-1 - perm-test-bindtype-test @@ -360,6 +395,7 @@ - name: Ensure testing groups are absent. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item }}" state: absent with_items: diff --git a/tests/permission/test_permission_client_context.yml b/tests/permission/test_permission_client_context.yml new file mode 100644 index 00000000..b351c086 --- /dev/null +++ b/tests/permission/test_permission_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test permission + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipapermission: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test permission using client context, in client host. + import_playbook: test_permission.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test permission using client context, in server host. + import_playbook: test_permission.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 368cee9364d432665ffef9ffb8a4acef94bbb6d5 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:38 -0300 Subject: [PATCH 20/32] ipaprivilege: Allow execution of plugin in client host. Update privilege README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/privilege/test_privilege_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-privilege.md | 1 + tests/privilege/test_privilege.yml | 20 +++++++++- .../test_privilege_client_context.yml | 38 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/privilege/test_privilege_client_context.yml diff --git a/README-privilege.md b/README-privilege.md index ddb78a1a..3b2537f8 100644 --- a/README-privilege.md +++ b/README-privilege.md @@ -133,6 +133,7 @@ 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 `name` \| `cn` | The list of privilege name strings. | yes `description` | Privilege description. | no `rename` \| `new_name` | Rename the privilege object. | no diff --git a/tests/privilege/test_privilege.yml b/tests/privilege/test_privilege.yml index 0f6a29d7..71c08d16 100644 --- a/tests/privilege/test_privilege.yml +++ b/tests/privilege/test_privilege.yml @@ -1,6 +1,6 @@ --- - name: Test privilege - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -10,6 +10,7 @@ - name: Ensure privilege "Broad Privilege" is absent ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - Broad Privilege - DNS Privilege @@ -22,6 +23,7 @@ - name: Ensure privilege Broad Privilege is present ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege description: Broad Privilege register: result @@ -30,6 +32,7 @@ - name: Ensure privilege Broad Privilege is present again ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege description: Broad Privilege register: result @@ -38,6 +41,7 @@ - name: Change privilege Broad Privilege description ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege description: Broad Privilege description register: result @@ -46,6 +50,7 @@ - name: Ensure privilege Broad Privilege has permissions ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege permission: - "Write IPA Configuration" @@ -58,6 +63,7 @@ - name: Ensure privilege Broad Privilege has permissions, again ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege permission: - "Write IPA Configuration" @@ -70,6 +76,7 @@ - name: Ensure privilege Broad Privilege member permission "Write IPA Configuration" is absent ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege permission: - "Write IPA Configuration" @@ -81,6 +88,7 @@ - name: Ensure privilege Broad Privilege member permission "Write IPA Configuration" is absent again ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege permission: - "Write IPA Configuration" @@ -92,6 +100,7 @@ - name: Ensure privilege Broad Privilege is absent ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege state: absent register: result @@ -100,6 +109,7 @@ - name: Ensure privilege Broad Privilege is present ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege register: result failed_when: not result.changed or result.failed @@ -107,6 +117,7 @@ - name: Ensure privilege Broad Privilege is renamed to "DNS Privilege" ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege rename: DNS Privilege state: renamed @@ -116,6 +127,7 @@ - name: Ensure privilege Broad Privilege cannot be renamed, because it does not exist. ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege rename: DNS Privilege state: renamed @@ -125,6 +137,7 @@ - name: Ensure privilege cannot be renamed to the same name. ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: DNS Privilege rename: DNS Privilege state: renamed @@ -134,6 +147,7 @@ - name: Ensure privilege cannot be renamed to the same name. ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: DNS Privilege rename: DNS Privilege state: renamed @@ -143,12 +157,14 @@ - name: Ensure "Broad Privilege" is absent. ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege state: absent - name: Ensure privilege Broad Privilege is created with permission. (issue 529) ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege permission: - "Write IPA Configuration" @@ -158,6 +174,7 @@ - name: Ensure privilege Broad Privilege is created with permission, again. (issue 529) ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: Broad Privilege permission: - "Write IPA Configuration" @@ -169,6 +186,7 @@ - name: Ensure privilege testing privileges are absent ipaprivilege: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - Broad Privilege - DNS Privilege diff --git a/tests/privilege/test_privilege_client_context.yml b/tests/privilege/test_privilege_client_context.yml new file mode 100644 index 00000000..cd125f75 --- /dev/null +++ b/tests/privilege/test_privilege_client_context.yml @@ -0,0 +1,38 @@ +--- +- name: Test privilege + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaprivilege: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test privilege using client context, in client host. + import_playbook: test_privilege.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test privilege using client context, in server host. + import_playbook: test_privilege.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] + From d5451cdacb0de74eac070c56c776462e0d69d5e7 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:40 -0300 Subject: [PATCH 21/32] ipapwpolicy: Allow execution of plugin in client host. Update pwpolicy README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/pwpolicy/test_pwpolicy_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-pwpolicy.md | 1 + tests/pwpolicy/test_pwpolicy.yml | 14 ++++++- .../pwpolicy/test_pwpolicy_client_context.yml | 38 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/pwpolicy/test_pwpolicy_client_context.yml diff --git a/README-pwpolicy.md b/README-pwpolicy.md index f0b5d885..94811596 100644 --- a/README-pwpolicy.md +++ b/README-pwpolicy.md @@ -98,6 +98,7 @@ 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 `name` \| `cn` | The list of pwpolicy name strings. If name is not given, `global_policy` will be used automatically. | no `maxlife` \| `krbmaxpwdlife` | Maximum password lifetime in days. (int) | no `minlife` \| `krbminpwdlife` | Minimum password lifetime in hours. (int) | no diff --git a/tests/pwpolicy/test_pwpolicy.yml b/tests/pwpolicy/test_pwpolicy.yml index 03f08e0f..5ac18d76 100644 --- a/tests/pwpolicy/test_pwpolicy.yml +++ b/tests/pwpolicy/test_pwpolicy.yml @@ -1,6 +1,6 @@ --- - name: Test pwpolicy - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,23 +8,27 @@ - name: Ensure maxlife of 90 for global_policy ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxlife: 90 - name: Ensure absence of group ops ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops state: absent - name: Ensure absence of pwpolicies for group ops ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops state: absent - name: Ensure presence of group ops ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops state: present register: result @@ -33,6 +37,7 @@ - name: Ensure presence of pwpolicies for group ops ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops minlife: 7 maxlife: 49 @@ -49,6 +54,7 @@ - name: Ensure presence of pwpolicies for group ops again ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops minlife: 7 maxlife: 49 @@ -65,6 +71,7 @@ - name: Ensure maxlife of 49 for global_policy ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxlife: 49 register: result failed_when: not result.changed or result.failed @@ -72,6 +79,7 @@ - name: Ensure maxlife of 49 for global_policy again ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxlife: 49 register: result failed_when: result.changed or result.failed @@ -79,6 +87,7 @@ - name: Ensure absence of pwpoliciy global_policy will fail ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" state: absent register: result failed_when: not result.failed or "'global_policy' can not be made absent." not in result.msg @@ -86,6 +95,7 @@ - name: Ensure absence of pwpolicies for group ops ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops state: absent register: result @@ -94,6 +104,7 @@ - name: Ensure maxlife of 90 for global_policy ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" maxlife: 90 register: result failed_when: not result.changed or result.failed @@ -101,6 +112,7 @@ - name: Ensure absence of pwpolicies for group ops ipapwpolicy: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: ops state: absent register: result diff --git a/tests/pwpolicy/test_pwpolicy_client_context.yml b/tests/pwpolicy/test_pwpolicy_client_context.yml new file mode 100644 index 00000000..362f567f --- /dev/null +++ b/tests/pwpolicy/test_pwpolicy_client_context.yml @@ -0,0 +1,38 @@ +--- +- name: Test pwpolicy + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipapwpolicy: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test pwpolicy using client context, in client host. + import_playbook: test_pwpolicy.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test pwpolicy using client context, in server host. + import_playbook: test_pwpolicy.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] + From c38b1e253949cea00184e87c63b37ed9f0d1f490 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:31:57 -0300 Subject: [PATCH 22/32] iparole: Allow execution of plugin in client host. Update role README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/role/test_role_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-role.md | 1 + tests/role/env_cleanup.yml | 6 ++++ tests/role/env_setup.yml | 5 ++++ tests/role/test_role.yml | 37 ++++++++++++++++++++++++- tests/role/test_role_client_context.yml | 37 +++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 tests/role/test_role_client_context.yml diff --git a/README-role.md b/README-role.md index 75248359..fc915c2b 100644 --- a/README-role.md +++ b/README-role.md @@ -245,6 +245,7 @@ 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 `name` \| `cn` | The list of role name strings. | yes `description` | A description for the role. | no `rename` \| `new_name` | Rename the role object. | no diff --git a/tests/role/env_cleanup.yml b/tests/role/env_cleanup.yml index 24064a1c..0b459651 100644 --- a/tests/role/env_cleanup.yml +++ b/tests/role/env_cleanup.yml @@ -2,6 +2,7 @@ - name: Ensure test user is absent. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - user01 - user02 @@ -11,6 +12,7 @@ - name: Ensure test group is absent. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - group01 - group02 @@ -19,6 +21,7 @@ - name: Ensure test hostgroup is absent. ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - hostgroup01 - hostgroup02 @@ -27,6 +30,7 @@ - name: Ensure test host is absent. ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ host1_fqdn }}" - "{{ host2_fqdn }}" @@ -35,6 +39,7 @@ - name: Ensure test service is absent. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "service01/{{ host1_fqdn }}" - "service02/{{ host2_fqdn }}" @@ -43,6 +48,7 @@ - name: Ensure test roles are absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - renamerole - testrole diff --git a/tests/role/env_setup.yml b/tests/role/env_setup.yml index 32bd32a9..eb72c82b 100644 --- a/tests/role/env_setup.yml +++ b/tests/role/env_setup.yml @@ -5,6 +5,7 @@ - name: Ensure test user is present. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" users: - name: user01 first: First @@ -19,6 +20,7 @@ - name: Ensure test group is present. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item }}" with_items: - group01 @@ -27,6 +29,7 @@ - name: Ensure test host is present. ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item }}" force: yes with_items: @@ -36,6 +39,7 @@ - name: Ensure test hostgroup is present. ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item[0] }}" host: - "{{ item[1] }}" @@ -46,6 +50,7 @@ - name: Ensure test service is present. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ item }}" force: yes with_items: diff --git a/tests/role/test_role.yml b/tests/role/test_role.yml index 0c4661e6..6f9ba90d 100644 --- a/tests/role/test_role.yml +++ b/tests/role/test_role.yml @@ -1,6 +1,6 @@ --- - name: Test role module - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: yes gather_facts: yes @@ -15,6 +15,7 @@ - name: Ensure role is present. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: renamerole description: A role in IPA. register: result @@ -23,6 +24,7 @@ - name: Ensure role is present, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: renamerole description: A role in IPA. register: result @@ -31,6 +33,7 @@ - name: Rename role. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: renamerole rename: testrole register: result @@ -41,6 +44,7 @@ - name: Rename role, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: renamerole rename: testrole register: result @@ -49,6 +53,7 @@ - name: Ensure role has member has privileges. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - DNS Servers @@ -60,6 +65,7 @@ - name: Ensure role has member has privileges, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - DNS Servers @@ -71,6 +77,7 @@ - name: Ensure role has less privileges. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - Host Administrators @@ -82,6 +89,7 @@ - name: Ensure role has less privileges, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - Host Administrators @@ -93,6 +101,7 @@ - name: Ensure role has member has privileges restored. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - DNS Servers @@ -104,6 +113,7 @@ - name: Ensure role has member has privileges restored, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - DNS Servers @@ -115,6 +125,7 @@ - name: Ensure role member privileges are absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - DNS Servers @@ -127,6 +138,7 @@ - name: Ensure role member privileges are absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: - DNS Servers @@ -139,6 +151,7 @@ - name: Ensure invalid privileged is not assigned to role. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole privilege: Invalid Privilege action: member @@ -148,6 +161,7 @@ - name: Ensure role has member user present. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole user: - user01 @@ -158,6 +172,7 @@ - name: Ensure role has member user present, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole user: - user01 @@ -168,6 +183,7 @@ - name: Ensure role has member user absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole user: - user01 @@ -179,6 +195,7 @@ - name: Ensure role has member user absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole user: - user01 @@ -190,6 +207,7 @@ - name: Ensure role has member group present. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole group: - group01 @@ -200,6 +218,7 @@ - name: Ensure role has member group present, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole group: - group01 @@ -210,6 +229,7 @@ - name: Ensure role has member group absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole group: - group01 @@ -221,6 +241,7 @@ - name: Ensure role has member group absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole group: - group01 @@ -232,6 +253,7 @@ - name: Ensure role has member host present. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole host: - "{{ host1_fqdn }}" @@ -242,6 +264,7 @@ - name: Ensure role has member host present, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole host: - "{{ host1_fqdn }}" @@ -252,6 +275,7 @@ - name: Ensure role has member host absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole host: - "{{ host1_fqdn }}" @@ -263,6 +287,7 @@ - name: Ensure role has member host absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole host: - "{{ host1_fqdn }}" @@ -274,6 +299,7 @@ - name: Ensure role has member hostgroup present. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole hostgroup: - hostgroup01 @@ -284,6 +310,7 @@ - name: Ensure role has member hostgroup present, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole hostgroup: - hostgroup01 @@ -294,6 +321,7 @@ - name: Ensure role has member hostgroup absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole hostgroup: - hostgroup01 @@ -305,6 +333,7 @@ - name: Ensure role has member hostgroup absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole hostgroup: - hostgroup01 @@ -316,6 +345,7 @@ - name: Ensure role is absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole state: absent register: result @@ -324,6 +354,7 @@ - name: Ensure role is absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole state: absent register: result @@ -332,6 +363,7 @@ - name: Ensure role with members is present. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole user: - user01 @@ -352,6 +384,7 @@ - name: Ensure role with members is present, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole user: - user01 @@ -372,6 +405,7 @@ - name: Ensure role is absent. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole state: absent register: result @@ -380,6 +414,7 @@ - name: Ensure role is absent, again. iparole: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrole state: absent register: result diff --git a/tests/role/test_role_client_context.yml b/tests/role/test_role_client_context.yml new file mode 100644 index 00000000..594d3ec1 --- /dev/null +++ b/tests/role/test_role_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test role + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + iparole: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test role using client context, in client host. + import_playbook: test_role.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test role using client context, in server host. + import_playbook: test_role.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 26dc8f1e535402affb64f7dd11459e0228a9c318 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:43 -0300 Subject: [PATCH 23/32] ipaserver: Allow execution of plugin in client host. Update server README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/server/test_server_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-server.md | 1 + tests/server/test_server.yml | 17 +++++++++- tests/server/test_server_client_context.yml | 37 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/server/test_server_client_context.yml diff --git a/README-server.md b/README-server.md index b899cdac..66e62bb5 100644 --- a/README-server.md +++ b/README-server.md @@ -230,6 +230,7 @@ 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 `name` \| `cn` | The list of server name strings. | yes `location` \| `ipalocation_location` | The server location string. Only in state: present. "" for location reset. | no `service_weight` \| `ipaserviceweight` | Weight for server services. Type Values 0 to 65535, -1 for weight reset. Only in state: present. (int) | no diff --git a/tests/server/test_server.yml b/tests/server/test_server.yml index b7f0193a..0f97b2ac 100644 --- a/tests/server/test_server.yml +++ b/tests/server/test_server.yml @@ -1,6 +1,6 @@ --- - name: Test server - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: yes @@ -30,18 +30,21 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without location ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" location: "" - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without service weight ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" service_weight: -1 - name: Ensure location "mylocation" is absent ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: mylocation state: absent @@ -50,6 +53,7 @@ - name: Ensure location "mylocation" is present ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: mylocation register: result failed_when: not result.changed or result.failed @@ -59,6 +63,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" is present ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" register: result failed_when: result.changed or result.failed @@ -66,6 +71,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with location "mylocation" ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" location: "mylocation" register: result @@ -74,6 +80,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with location "mylocation" again ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" location: "mylocation" register: result @@ -82,6 +89,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without location ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" location: "" register: result @@ -90,6 +98,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without location again ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" location: "" register: result @@ -98,6 +107,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with service weight 1 ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" service_weight: 1 register: result @@ -106,6 +116,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with service weight 1 again ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" service_weight: 1 register: result @@ -114,6 +125,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without service weight ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" service_weight: -1 register: result @@ -122,6 +134,7 @@ - name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without service weight again ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ ipa_server_name + '.' + ipaserver_domain }}" service_weight: -1 register: result @@ -134,6 +147,7 @@ - name: Ensure server "{{ 'absent.' + ipaserver_domain }}" is absent ipaserver: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ 'absent.' + ipaserver_domain }}" state: absent register: result @@ -148,6 +162,7 @@ - name: Ensure location "mylocation" is absent ipalocation: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: mylocation state: absent register: result diff --git a/tests/server/test_server_client_context.yml b/tests/server/test_server_client_context.yml new file mode 100644 index 00000000..d1f31090 --- /dev/null +++ b/tests/server/test_server_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test server + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaserver: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test server using client context, in client host. + import_playbook: test_server.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test server using client context, in server host. + import_playbook: test_server.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 198e2152f59b5f7cb54edf52fc557ceb6ecc358a Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:45 -0300 Subject: [PATCH 24/32] ipasudocmd: Allow execution of plugin in client host. Update sudocmd README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/sudocmd/test_sudocmd_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-sudocmd.md | 1 + tests/sudocmd/test_sudocmd.yml | 15 +++++++- tests/sudocmd/test_sudocmd_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/sudocmd/test_sudocmd_client_context.yml diff --git a/README-sudocmd.md b/README-sudocmd.md index e68fa01d..2c30ddbf 100644 --- a/README-sudocmd.md +++ b/README-sudocmd.md @@ -83,6 +83,7 @@ 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 `name` \| `sudocmd` | The sudo command strings. | yes `description` | The command description string. | no `nomembers` | Suppress processing of membership attributes. (bool) | no diff --git a/tests/sudocmd/test_sudocmd.yml b/tests/sudocmd/test_sudocmd.yml index 992dba7d..f41cd991 100644 --- a/tests/sudocmd/test_sudocmd.yml +++ b/tests/sudocmd/test_sudocmd.yml @@ -1,7 +1,7 @@ --- - name: Test sudocmd - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -9,6 +9,7 @@ - name: Ensure sudocmds are absent ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/bin/su - /usr/sbin/ifconfig @@ -18,6 +19,7 @@ - name: Ensure sudocmd is present ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: /usr/bin/su state: present register: result @@ -26,6 +28,7 @@ - name: Ensure sudocmd is present again ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: /usr/bin/su state: present register: result @@ -34,6 +37,7 @@ - name: Ensure sudocmd is absent ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: /usr/bin/su state: absent register: result @@ -42,6 +46,7 @@ - name: Ensure sudocmd is absent again ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: /usr/bin/su state: absent register: result @@ -50,6 +55,7 @@ - name: Ensure multiple sudocmd are present ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/ifconfig - /usr/sbin/iwlist @@ -60,6 +66,7 @@ - name: Ensure multiple sudocmd are present again ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/ifconfig - /usr/sbin/iwlist @@ -70,6 +77,7 @@ - name: Ensure multiple sudocmd are absent ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/ifconfig - /usr/sbin/iwlist @@ -80,6 +88,7 @@ - name: Ensure multiple sudocmd are absent again ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/ifconfig - /usr/sbin/iwlist @@ -90,6 +99,7 @@ - name: Ensure sudocmds are absent ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/bin/su - /usr/sbin/ifconfig @@ -99,6 +109,7 @@ - name: Ensure sudocmds are absent ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/ifconfig state: absent @@ -106,6 +117,7 @@ - name: Ensure sudocmds are present ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/iwlist state: present @@ -113,6 +125,7 @@ - name: Ensure multiple sudocmd are absent when only one was present ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/sbin/ifconfig - /usr/sbin/iwlist diff --git a/tests/sudocmd/test_sudocmd_client_context.yml b/tests/sudocmd/test_sudocmd_client_context.yml new file mode 100644 index 00000000..48f51756 --- /dev/null +++ b/tests/sudocmd/test_sudocmd_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test sudocmd + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipasudocmd: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test sudocmd using client context, in client host. + import_playbook: test_sudocmd.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test sudocmd using client context, in server host. + import_playbook: test_sudocmd.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 3cd99781719604687cb726e33a101c6c349cad43 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:48 -0300 Subject: [PATCH 25/32] ipasudocmdgroup: Allow execution of plugin in client host. Update sudocmdgroup README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/sudocmdgroup/test_sudocmdgroup_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-sudocmdgroup.md | 1 + tests/sudocmdgroup/test_sudocmdgroup.yml | 22 ++++++++++- .../test_sudocmdgroup_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/sudocmdgroup/test_sudocmdgroup_client_context.yml diff --git a/README-sudocmdgroup.md b/README-sudocmdgroup.md index cca08c19..e37f577a 100644 --- a/README-sudocmdgroup.md +++ b/README-sudocmdgroup.md @@ -123,6 +123,7 @@ 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 `name` \| `cn` | The list of sudocmdgroup name strings. | no `description` | The sudocmdgroup description string. | no `nomembers` | Suppress processing of membership attributes. (bool) | no diff --git a/tests/sudocmdgroup/test_sudocmdgroup.yml b/tests/sudocmdgroup/test_sudocmdgroup.yml index 17c60885..59f63061 100644 --- a/tests/sudocmdgroup/test_sudocmdgroup.yml +++ b/tests/sudocmdgroup/test_sudocmdgroup.yml @@ -1,6 +1,6 @@ --- - name: Test sudocmdgroup - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,6 +8,7 @@ - name: Ensure sudocmds are present ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /usr/bin/su - /usr/sbin/ifconfig @@ -17,12 +18,14 @@ - name: Ensure sudocmdgroup is absent ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: absent - name: Ensure sudocmdgroup is present ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: present register: result @@ -31,6 +34,7 @@ - name: Ensure sudocmdgroup is present again ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: present register: result @@ -39,6 +43,7 @@ - name: Ensure sudocmdgroup is absent ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: absent register: result @@ -47,6 +52,7 @@ - name: Ensure sudocmdgroup is absent again ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: absent register: result @@ -55,6 +61,7 @@ - name: Ensure sudocmdgroup is present, with sudocmds. ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -66,6 +73,7 @@ - name: Ensure sudocmdgroup is present, with sudocmds, again. ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -85,6 +93,7 @@ - name: Ensure sudocmdgroup, with sudocmds, is absent ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: absent register: result @@ -93,6 +102,7 @@ - name: Ensure sudocmdgroup, with sudocmds, is absent again ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: absent register: result @@ -101,6 +111,7 @@ - name: Ensure testing sudocmdgroup is present ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network state: present register: result @@ -109,6 +120,7 @@ - name: Ensure sudo commands are present in existing sudocmdgroup ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -120,6 +132,7 @@ - name: Ensure sudo commands are present in existing sudocmdgroup, again ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -131,6 +144,7 @@ - name: Ensure sudo commands are absent in existing sudocmdgroup ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -143,6 +157,7 @@ - name: Ensure sudo commands are absent in existing sudocmdgroup, again ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -155,6 +170,7 @@ - name: Ensure sudo commands are present in sudocmdgroup ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -167,6 +183,7 @@ - name: Ensure one sudo command is not present in sudocmdgroup ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -178,6 +195,7 @@ - name: Ensure one sudo command is present in sudocmdgroup ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/ifconfig @@ -189,6 +207,7 @@ - name: Ensure the other sudo command is not present in sudocmdgroup ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/iwlist @@ -200,6 +219,7 @@ - name: Ensure the other sudo commandsis not present in sudocmdgroup, again ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: network sudocmd: - /usr/sbin/iwlist diff --git a/tests/sudocmdgroup/test_sudocmdgroup_client_context.yml b/tests/sudocmdgroup/test_sudocmdgroup_client_context.yml new file mode 100644 index 00000000..c5a3ae67 --- /dev/null +++ b/tests/sudocmdgroup/test_sudocmdgroup_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test sudocmdgroup + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipasudocmdgroup: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test sudocmdgroup using client context, in client host. + import_playbook: test_sudocmdgroup.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test sudocmdgroup using client context, in server host. + import_playbook: test_sudocmdgroup.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 829f10568a4b61bb2a6f6455cdf25521a73d1cf5 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:51 -0300 Subject: [PATCH 26/32] ipasudorule: Allow execution of plugin in client host. Update sudorule README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/sudorule/test_sudorule_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-sudorule.md | 1 + tests/sudorule/test_sudorule.yml | 83 ++++++++++++++++++- .../sudorule/test_sudorule_client_context.yml | 37 +++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 tests/sudorule/test_sudorule_client_context.yml diff --git a/README-sudorule.md b/README-sudorule.md index b973c369..f7954489 100644 --- a/README-sudorule.md +++ b/README-sudorule.md @@ -120,6 +120,7 @@ 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 `name` \| `cn` | The list of sudorule name strings. | yes `description` | The sudorule description string. | no `usercategory` \| `usercat` | User category the rule applies to. Choices: ["all", ""] | no diff --git a/tests/sudorule/test_sudorule.yml b/tests/sudorule/test_sudorule.yml index 3b01a085..dc37e77a 100644 --- a/tests/sudorule/test_sudorule.yml +++ b/tests/sudorule/test_sudorule.yml @@ -1,7 +1,7 @@ --- - name: Test sudorule - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: true @@ -11,18 +11,21 @@ - name: Ensure user is absent ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: user01 state: absent - name: Ensure group is absent ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group01 state: absent - name: Ensure user is present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: user01 first: user last: zeroone @@ -30,24 +33,28 @@ - name: Ensure group is present, with user01 on it. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group01 user: user01 - name: Ensure sudocmdgroup is absent ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test_sudorule state: absent - name: Ensure hostgroup is present, with a host. ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: cluster host: "{{ ansible_facts['fqdn'] }}" - name: Ensure some sudocmds are available ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /sbin/ifconfig - /usr/bin/vim @@ -56,6 +63,7 @@ - name: Ensure sudocmdgroup is available ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test_sudorule sudocmd: /usr/bin/vim state: present @@ -63,6 +71,7 @@ - name: Ensure sudorules are absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - testrule1 - allusers @@ -75,6 +84,7 @@ - name: Ensure sudorule is present ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 register: result failed_when: not result.changed or result.failed @@ -82,6 +92,7 @@ - name: Ensure sudorule is present again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 register: result failed_when: result.changed or result.failed @@ -89,6 +100,7 @@ - name: Ensure user01 is on the list of users sudorule execute as. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasuser: - user01 @@ -99,6 +111,7 @@ - name: Ensure user01 is on the list of users sudorule execute as, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasuser: - user01 @@ -109,6 +122,7 @@ - name: Ensure user01 is not on the list of users sudorule execute as. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasuser: - user01 @@ -120,6 +134,7 @@ - name: Ensure user01 is not on the list of users sudorule execute as, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasuser: - user01 @@ -131,6 +146,7 @@ - name: Ensure group01 is on the list of group sudorule execute as. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasgroup: - group01 @@ -141,6 +157,7 @@ - name: Ensure group01 is on the list of group sudorule execute as, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasgroup: - group01 @@ -151,6 +168,7 @@ - name: Ensure group01 is not on the list of group sudorule execute as. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasgroup: - group01 @@ -162,6 +180,7 @@ - name: Ensure group01 is not on the list of groups sudorule execute as, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 runasgroup: - group01 @@ -173,6 +192,7 @@ - name: Ensure sudorule is present, with usercategory 'all' ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers usercategory: all register: result @@ -181,6 +201,7 @@ - name: Ensure sudorule is present, with usercategory 'all', again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers usercategory: all register: result @@ -189,6 +210,7 @@ - name: Ensure sudorule is with usercategory 'all' is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers state: absent register: result @@ -197,6 +219,7 @@ - name: Ensure sudorule is present, with runasusercategory 'all'. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers runasusercategory: all register: result @@ -205,6 +228,7 @@ - name: Ensure sudorule is present, with runasusercategory 'all', again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers runasusercategory: all register: result @@ -213,6 +237,7 @@ - name: Ensure sudorule is with runasusercategory 'all' is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers state: absent register: result @@ -221,6 +246,7 @@ - name: Ensure sudorule is present, with runasgroupcategory 'all'. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers runasgroupcategory: all register: result @@ -229,6 +255,7 @@ - name: Ensure sudorule is present, with runasgroupcategory 'all', again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers runasgroupcategory: all register: result @@ -237,6 +264,7 @@ - name: Ensure sudorule is with runasgroupcategory 'all' is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers state: absent register: result @@ -245,6 +273,7 @@ - name: Ensure sudorule is present, with usercategory 'all'. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers usercategory: all register: result @@ -253,6 +282,7 @@ - name: Ensure sudorule is present, with usercategory 'all', again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers usercategory: all register: result @@ -261,6 +291,7 @@ - name: Ensure sudorule is present, with hostategory 'all' ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allhosts hostcategory: all register: result @@ -269,6 +300,7 @@ - name: Ensure sudorule is present, with hostategory 'all', again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allhosts hostcategory: all register: result @@ -277,6 +309,7 @@ - name: Ensure sudorule is disabled ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 state: disabled register: result @@ -285,6 +318,7 @@ - name: Ensure sudorule is disabled, again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 state: disabled register: result @@ -293,6 +327,7 @@ - name: Ensure sudorule is enabled ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 state: enabled register: result @@ -301,6 +336,7 @@ - name: Ensure sudorule is enabled, again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 state: enabled register: result @@ -309,6 +345,7 @@ - name: Ensure user is present in sudorule. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 user: user01 action: member @@ -318,6 +355,7 @@ - name: Ensure user is present in sudorule, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 user: user01 action: member @@ -327,6 +365,7 @@ - name: Ensure user is absent from sudorule. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 user: user01 action: member @@ -337,6 +376,7 @@ - name: Ensure user is absent from sudorule, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 user: user01 action: member @@ -347,6 +387,7 @@ - name: Ensure group is present in sudorule. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 group: group01 action: member @@ -356,6 +397,7 @@ - name: Ensure group is present in sudorule, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 group: group01 action: member @@ -365,6 +407,7 @@ - name: Ensure group is absent from sudorule. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 group: group01 action: member @@ -375,6 +418,7 @@ - name: Ensure group is absent from sudorule, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 group: group01 action: member @@ -385,6 +429,7 @@ - name: Ensure sudorule has a sudooption. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 sudooption: '!authenticate' action: member @@ -394,6 +439,7 @@ - name: Ensure sudorule has a sudooption, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 sudooption: '!authenticate' action: member @@ -403,6 +449,7 @@ - name: Ensure sudorule has an order. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 order: 1 register: result @@ -411,6 +458,7 @@ - name: Ensure sudorule has an order, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 order: 1 register: result @@ -419,6 +467,7 @@ - name: Ensure sudorule has another order. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 order: 10 register: result @@ -427,6 +476,7 @@ - name: Ensure sudorule is present and some sudocmd are allowed. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmd: - /sbin/ifconfig @@ -437,6 +487,7 @@ - name: Ensure sudorule is present and some sudocmd are allowed, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmd: - /sbin/ifconfig @@ -447,6 +498,7 @@ - name: Ensure sudorule is present and some sudocmd are denyed. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 deny_sudocmd: - /usr/bin/vim @@ -457,6 +509,7 @@ - name: Ensure sudorule is present and some sudocmd are denyed, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 deny_sudocmd: - /usr/bin/vim @@ -467,6 +520,7 @@ - name: Ensure sudorule is present and, sudocmds are absent. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmd: /sbin/ifconfig deny_sudocmd: /usr/bin/vim @@ -478,6 +532,7 @@ - name: Ensure sudorule is present and, sudocmds are absent, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmd: /sbin/ifconfig deny_sudocmd: /usr/bin/vim @@ -489,6 +544,7 @@ - name: Ensure sudorule is present with cmdcategory 'all'. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allcommands cmdcategory: all register: result @@ -497,6 +553,7 @@ - name: Ensure sudorule is present with cmdcategory 'all', again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allcommands cmdcategory: all register: result @@ -505,6 +562,7 @@ - name: Ensure host "{{ ansible_facts['fqdn'] }}" is present in sudorule. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 host: "{{ ansible_facts['fqdn'] }}" action: member @@ -514,6 +572,7 @@ - name: Ensure host "{{ ansible_facts['fqdn'] }}" is present in sudorule, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 host: "{{ ansible_facts['fqdn'] }}" action: member @@ -523,6 +582,7 @@ - name: Ensure hostgroup is present in sudorule. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 hostgroup: cluster action: member @@ -532,6 +592,7 @@ - name: Ensure hostgroup is present in sudorule, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 hostgroup: cluster action: member @@ -541,6 +602,7 @@ - name: Ensure sudorule is present, with an allow_sudocmdgroup. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmdgroup: test_sudorule state: present @@ -550,6 +612,7 @@ - name: Ensure sudorule is present, with an allow_sudocmdgroup, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmdgroup: test_sudorule state: present @@ -559,6 +622,7 @@ - name: Ensure sudorule is present, but allow_sudocmdgroup is absent. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmdgroup: test_sudorule action: member @@ -569,6 +633,7 @@ - name: Ensure sudorule is present, but allow_sudocmdgroup is absent. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 allow_sudocmdgroup: test_sudorule action: member @@ -579,6 +644,7 @@ - name: Ensure sudorule is present, with an deny_sudocmdgroup. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 deny_sudocmdgroup: test_sudorule state: present @@ -588,6 +654,7 @@ - name: Ensure sudorule is present, with an deny_sudocmdgroup, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 deny_sudocmdgroup: test_sudorule state: present @@ -597,6 +664,7 @@ - name: Ensure sudorule is present, but deny_sudocmdgroup is absent. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 deny_sudocmdgroup: test_sudorule action: member @@ -607,6 +675,7 @@ - name: Ensure sudorule is present, but deny_sudocmdgroup is absent, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 deny_sudocmdgroup: test_sudorule action: member @@ -617,6 +686,7 @@ - name: Ensure sudorule is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 state: absent register: result @@ -625,6 +695,7 @@ - name: Ensure sudorule is absent, again. ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: testrule1 state: absent register: result @@ -633,6 +704,7 @@ - name: Ensure sudorule allhosts is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allhosts state: absent register: result @@ -641,6 +713,7 @@ - name: Ensure sudorule allhosts is absent, again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allhosts state: absent register: result @@ -649,6 +722,7 @@ - name: Ensure sudorule allusers is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers state: absent register: result @@ -657,6 +731,7 @@ - name: Ensure sudorule allusers is absent, again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allusers state: absent register: result @@ -665,6 +740,7 @@ - name: Ensure sudorule allcommands is absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allcommands state: absent register: result @@ -673,6 +749,7 @@ - name: Ensure sudorule allcommands is absent, again ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: allcommands state: absent register: result @@ -682,12 +759,14 @@ - name : Ensure sudocmdgroup is absent ipasudocmdgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: test_sudorule state: absent - name: Ensure sudocmds are absent ipasudocmd: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - /sbin/ifconfig - /usr/bin/vim @@ -696,6 +775,7 @@ - name: Ensure sudorules are absent ipasudorule: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - testrule1 - allusers @@ -706,5 +786,6 @@ - name: Ensure hostgroup is absent. ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: cluster state: absent diff --git a/tests/sudorule/test_sudorule_client_context.yml b/tests/sudorule/test_sudorule_client_context.yml new file mode 100644 index 00000000..65647cd9 --- /dev/null +++ b/tests/sudorule/test_sudorule_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test sudorule + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipasudorule: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test sudorule using client context, in client host. + import_playbook: test_sudorule.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test sudorule using client context, in server host. + import_playbook: test_sudorule.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 577d8f789368fafc6a978dbacd3ae7430839fa06 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:53 -0300 Subject: [PATCH 27/32] ipatrust: Allow execution of plugin in client host. Update trust README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/trust/test_trust_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-trust.md | 1 + tests/trust/test_trust.yml | 4 ++- tests/trust/test_trust_client_context.yml | 38 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/trust/test_trust_client_context.yml diff --git a/README-trust.md b/README-trust.md index bc16bd30..603303e1 100644 --- a/README-trust.md +++ b/README-trust.md @@ -101,6 +101,7 @@ 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 `realm` | The realm name string. | yes `admin` | Active Directory domain administrator string. | no `password` | Active Directory domain administrator's password string. | no diff --git a/tests/trust/test_trust.yml b/tests/trust/test_trust.yml index 581c6828..e4ecdf50 100644 --- a/tests/trust/test_trust.yml +++ b/tests/trust/test_trust.yml @@ -1,6 +1,6 @@ --- - name: find trust - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -11,6 +11,7 @@ - name: delete trust ipatrust: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" realm: windows.local state: absent register: del_trust @@ -38,6 +39,7 @@ - name: add trust ipatrust: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" realm: windows.local admin: Administrator password: secret_ad_pw diff --git a/tests/trust/test_trust_client_context.yml b/tests/trust/test_trust_client_context.yml new file mode 100644 index 00000000..0b53cc53 --- /dev/null +++ b/tests/trust/test_trust_client_context.yml @@ -0,0 +1,38 @@ +--- +- name: Test trust + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipatrust: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + realm: windows.local + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test trust using client context, in client host. + import_playbook: test_trust.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test trust using client context, in server host. + import_playbook: test_trust.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] + From 27b50957d17c8082a7abe45c90af9748d2841fd6 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:28:56 -0300 Subject: [PATCH 28/32] ipauser: Allow execution of plugin in client host. Update user README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/user/test_user_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-user.md | 1 + tests/user/test_user.yml | 26 ++++++++++++++++- tests/user/test_user_client_context.yml | 37 +++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/user/test_user_client_context.yml diff --git a/README-user.md b/README-user.md index 0a7cc6a8..7b88f594 100644 --- a/README-user.md +++ b/README-user.md @@ -365,6 +365,7 @@ 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 `name` | The list of user name strings. `name` with *user variables* or `users` containing *user variables* need to be used. | no **User variables** | Only used with `name` variable in the first level. | no `users` | The list of user dicts. Each `users` dict entry can contain **user variables**.
There is one required option in the `users` dict:| no diff --git a/tests/user/test_user.yml b/tests/user/test_user.yml index 5246d14c..571a7bab 100644 --- a/tests/user/test_user.yml +++ b/tests/user/test_user.yml @@ -1,6 +1,6 @@ --- - name: Test user - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true gather_facts: false @@ -8,12 +8,14 @@ - name: Remove test users ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: manager1,manager2,manager3,pinky,pinky2 state: absent - name: User manager1 present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: manager1 first: Manager last: One @@ -23,6 +25,7 @@ - name: User manager2 present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: manager2 first: Manager last: One @@ -32,6 +35,7 @@ - name: User manager3 present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: manager3 first: Manager last: One @@ -41,6 +45,7 @@ - name: User pinky present ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky uid: 10001 gid: 100 @@ -84,6 +89,7 @@ - name: User pinky present with changed settings ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky first: pinky last: Acme @@ -98,6 +104,7 @@ - name: User pinky add manager manager1 ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky manager: manager1 action: member @@ -107,6 +114,7 @@ - name: User pinky add manager manager1 again ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky manager: manager1 action: member @@ -116,6 +124,7 @@ - name: User pinky add manager manager2, manager3 ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky manager: manager2,manager3 action: member @@ -125,6 +134,7 @@ - name: User pinky add manager manager2, manager3 again ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky manager: manager2,manager3 action: member @@ -134,6 +144,7 @@ - name: User pinky remove manager manager1 ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky manager: manager1 action: member @@ -144,6 +155,7 @@ - name: User pinky remove manager manager1 again ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky manager: manager1 action: member @@ -154,6 +166,7 @@ - name: User pinky add principal pa ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa action: member @@ -163,6 +176,7 @@ - name: User pinky add principal pa again ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa action: member @@ -172,6 +186,7 @@ - name: User pinky add principal pa1 ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa1 action: member @@ -181,6 +196,7 @@ - name: User pinky remove principal pa1 ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa1 action: member @@ -191,6 +207,7 @@ - name: User pinky remove principal pa1 again ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa1 action: member @@ -201,6 +218,7 @@ - name: User pinky remove principal pa ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa action: member @@ -211,6 +229,7 @@ - name: User pinky remove principal non-existing pa2 ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky principal: pa2 action: member @@ -221,6 +240,7 @@ - name: User pinky absent and preserved ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky preserve: yes state: absent @@ -230,6 +250,7 @@ - name: User pinky undeleted (preserved before) ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky state: undeleted register: result @@ -238,6 +259,7 @@ - name: Users pinky disabled ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky state: disabled register: result @@ -246,6 +268,7 @@ - name: User pinky enabled ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: pinky state: enabled register: result @@ -254,5 +277,6 @@ - name: Remove test users ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: manager1,manager2,manager3,pinky,pinky2 state: absent diff --git a/tests/user/test_user_client_context.yml b/tests/user/test_user_client_context.yml new file mode 100644 index 00000000..d09b6883 --- /dev/null +++ b/tests/user/test_user_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test user + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test user using client context, in client host. + import_playbook: test_user.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test user using client context, in server host. + import_playbook: test_user.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From f1381edcd4fd7641de095739e0d46cc146c66d06 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:31:57 -0300 Subject: [PATCH 29/32] ipaservice: Allow execution of plugin in client host. Update service README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/service/test_service_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-service.md | 1 + tests/service/env_cleanup.yml | 8 ++++ tests/service/env_setup.yml | 8 ++++ tests/service/test_service.yml | 42 ++++++++++++++++++- tests/service/test_service_client_context.yml | 37 ++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/service/test_service_client_context.yml diff --git a/README-service.md b/README-service.md index b6a014ed..0cc6b879 100644 --- a/README-service.md +++ b/README-service.md @@ -291,6 +291,7 @@ 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 `name` \| `service` | The list of service name strings. | yes `certificate` \| `usercertificate` | Base-64 encoded service certificate. | no `pac_type` \| `ipakrbauthzdata` | Supported PAC type. It can be one of `MS-PAC`, `PAD`, or `NONE`. | no diff --git a/tests/service/env_cleanup.yml b/tests/service/env_cleanup.yml index 1a137bbe..964807d2 100644 --- a/tests/service/env_cleanup.yml +++ b/tests/service/env_cleanup.yml @@ -3,6 +3,7 @@ - name: Ensure services are absent. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "HTTP/{{ svc_fqdn }}" - "HTTP/{{ nohost_fqdn }}" @@ -16,6 +17,7 @@ - name: Ensure host "{{ svc_fqdn }}" is absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ svc_fqdn }}" update_dns: yes state: absent @@ -23,6 +25,7 @@ - name: Ensure host is absent ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "{{ host1_fqdn }}" - "{{ host2_fqdn }}" @@ -34,6 +37,7 @@ - name: Ensure testing users are absent. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - user01 - user02 @@ -42,6 +46,7 @@ - name: Ensure testing groups are absent. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - group01 - group02 @@ -50,6 +55,7 @@ - name: Ensure testing hostgroup hostgroup01 is absent. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - hostgroup01 state: absent @@ -57,6 +63,7 @@ - name: Ensure testing hostgroup hostgroup02 is absent. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - hostgroup02 state: absent @@ -64,6 +71,7 @@ - name: Remove IP address for "nohost" host. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ test_domain }}." name: nohost del_all: yes diff --git a/tests/service/env_setup.yml b/tests/service/env_setup.yml index 8f2e2866..9c92a64e 100644 --- a/tests/service/env_setup.yml +++ b/tests/service/env_setup.yml @@ -10,6 +10,7 @@ - name: Add IP address for "nohost" host. ipadnsrecord: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" zone_name: "{{ test_domain }}." name: nohost a_ip_address: "{{ ipv4_prefix + '.100' }}" @@ -17,6 +18,7 @@ - name: Add hosts for tests. ipahost: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" hosts: - name: "{{ host1_fqdn }}" ip_address: "{{ ipv4_prefix + '.101' }}" @@ -31,6 +33,7 @@ - name: Ensure testing user user01 is present. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: user01 first: user01 last: last @@ -38,6 +41,7 @@ - name: Ensure testing user user02 is present. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: user02 first: user02 last: last @@ -45,19 +49,23 @@ - name: Ensure testing group group01 is present. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group01 - name: Ensure testing group group02 is present. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: group02 - name: Ensure testing hostgroup hostgroup01 is present. ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hostgroup01 - name: Ensure testing hostgroup hostgroup02 is present. ipahostgroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: hostgroup02 diff --git a/tests/service/test_service.yml b/tests/service/test_service.yml index 0c1683d1..3436f032 100644 --- a/tests/service/test_service.yml +++ b/tests/service/test_service.yml @@ -12,7 +12,7 @@ # --- - name: Test service - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: yes tasks: @@ -28,6 +28,7 @@ - name: Ensure service is present ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" pac_type: - MS-PAC @@ -44,6 +45,7 @@ - name: Ensure service is present, again ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" pac_type: - MS-PAC @@ -60,6 +62,7 @@ - name: Modify service. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" pac_type: NONE ok_as_delegate: yes @@ -70,6 +73,7 @@ - name: Modify service, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" pac_type: NONE ok_as_delegate: yes @@ -80,6 +84,7 @@ - name: Ensure service is present, without host object. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ nohost_fqdn }}" skip_host_check: yes register: result @@ -88,6 +93,7 @@ - name: Ensure service is present, without host object, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ nohost_fqdn }}" skip_host_check: yes register: result @@ -96,6 +102,7 @@ - name: Ensure service is present, with host not in DNS. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: HTTP/svc.ihavenodns.info skip_host_check: no force: yes @@ -105,6 +112,7 @@ - name: Ensure service is present, with host not in DNS, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: HTTP/svc.ihavenodns.info skip_host_check: no force: yes @@ -114,6 +122,7 @@ - name: Ensure service is present, whithout host object and with host not in DNS. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: HTTP/no.idontexist.info skip_host_check: yes force: yes @@ -123,6 +132,7 @@ - name: Ensure service is present, whithout host object and with host not in DNS, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: HTTP/no.idontexist.info skip_host_check: yes force: yes @@ -132,6 +142,7 @@ - name: Principal host/test.example.com present in service. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" principal: - host/test.example.com @@ -142,6 +153,7 @@ - name: Principal host/test.example.com present in service, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" principal: - host/test.example.com @@ -153,6 +165,7 @@ - name: Principal host/test.example.com absent in service. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" principal: - host/test.example.com @@ -164,6 +177,7 @@ - name: Principal host/test.example.com absent in service, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" principal: - host/test.example.com @@ -176,6 +190,7 @@ - name: Ensure host can manage service. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" host: - "{{ host1_fqdn }}" @@ -187,6 +202,7 @@ - name: Ensure host can manage service, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" host: "{{ host1_fqdn }}" action: member @@ -196,6 +212,7 @@ - name: Ensure host cannot manage service. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" host: - "{{ host1_fqdn }}" @@ -208,6 +225,7 @@ - name: Ensure host cannot manage service, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" host: - "{{ host1_fqdn }}" @@ -220,6 +238,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, groups, hosts and hostgroups. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_create_keytab_user: - user01 @@ -240,6 +259,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, groups, hosts and hostgroups, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_create_keytab_user: - user01 @@ -260,6 +280,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, groups, hosts and hostgroups. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_create_keytab_user: - user01 @@ -281,6 +302,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, groups, hosts and hostgroups, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_create_keytab_user: - user01 @@ -302,6 +324,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, groups, hosts and hostgroups ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_retrieve_keytab_user: - user01 @@ -322,6 +345,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, groups, hosts and hostgroups, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_retrieve_keytab_user: - user01 @@ -342,6 +366,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, groups, hosts and hostgroups. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_retrieve_keytab_user: - user01 @@ -363,6 +388,7 @@ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, groups, hosts and hostgroups, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" allow_retrieve_keytab_user: - user01 @@ -384,6 +410,7 @@ - name: Ensure service is absent ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" continue: yes state: absent @@ -393,6 +420,7 @@ - name: Ensure service is absent, again ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" continue: yes state: absent @@ -402,6 +430,7 @@ - name: Ensure service is present, with multiple auth_ind values. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" auth_ind: otp,radius skip_host_check: no @@ -412,6 +441,7 @@ - name: Ensure service is present, with multiple auth_ind values, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" auth_ind: otp,radius skip_host_check: no @@ -422,6 +452,7 @@ - name: Clear auth_ind. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" auth_ind: "" skip_host_check: no @@ -432,6 +463,7 @@ - name: Clear auth_ind, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "HTTP/{{ svc_fqdn }}" auth_ind: "" skip_host_check: no @@ -442,6 +474,7 @@ - name: Ensure services are absent. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "HTTP/{{ svc_fqdn }}" - "HTTP/{{ nohost_fqdn }}" @@ -455,6 +488,7 @@ - name: Ensure services are absent. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - "HTTP/{{ svc_fqdn }}" - "HTTP/{{ nohost_fqdn }}" @@ -468,6 +502,7 @@ - name: Ensure SMB service is present. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host1_fqdn }}" pac_type: NONE smb: yes @@ -478,6 +513,7 @@ - name: Ensure SMB service is again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host1_fqdn }}" pac_type: NONE smb: yes @@ -488,6 +524,7 @@ - name: Modify SMB service. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host1_fqdn }}" smb: yes netbiosname: SAMBASVC @@ -503,6 +540,7 @@ - name: Modify SMB service, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "{{ host1_fqdn }}" smb: yes netbiosname: SAMBASVC @@ -518,6 +556,7 @@ - name: Ensure SMB service is absent. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "cifs/{{ host1_fqdn }}" continue: yes state: absent @@ -527,6 +566,7 @@ - name: Ensure SMB service is absent, again. ipaservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "cifs/{{ host1_fqdn }}" continue: yes state: absent diff --git a/tests/service/test_service_client_context.yml b/tests/service/test_service_client_context.yml new file mode 100644 index 00000000..9b27dc48 --- /dev/null +++ b/tests/service/test_service_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test service + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaservice: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test service using client context, in client host. + import_playbook: test_service.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test service using client context, in server host. + import_playbook: test_service.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From 63423779a84d5e367082143b57ba601efb4c15f0 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:47:13 -0300 Subject: [PATCH 30/32] ipaselfservice: Allow execution of plugin in client host. Update selfservice README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/selfservice/test_selfservice_client_context.yml The new test file can be executed in a FreeIPA client host that is not a server. In this case, it should be defined in the `ipaclients` group, in the inventory file. --- README-selfservice.md | 1 + tests/selfservice/test_selfservice.yml | 17 ++++++++- .../test_selfservice_client_context.yml | 37 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/selfservice/test_selfservice_client_context.yml diff --git a/README-selfservice.md b/README-selfservice.md index ae6a8a3e..8bfa8352 100644 --- a/README-selfservice.md +++ b/README-selfservice.md @@ -138,6 +138,7 @@ 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 `name` \| `aciname` | The list of selfservice name strings. | yes `permission` \| `permissions` | The permission to grant `read`, `read,write`, `write`]. Default is `write`. | no `attribute` \| `attrs` | The attribute list to which the selfservice applies. | no diff --git a/tests/selfservice/test_selfservice.yml b/tests/selfservice/test_selfservice.yml index 3f036acb..a5305187 100644 --- a/tests/selfservice/test_selfservice.yml +++ b/tests/selfservice/test_selfservice.yml @@ -1,6 +1,6 @@ --- - name: Test selfservice - hosts: ipaserver + hosts: "{{ ipa_test_host | default('ipaserver') }}" become: true tasks: @@ -10,6 +10,7 @@ - name: Ensure selfservice "Users can manage their own name details" is absent ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" state: absent @@ -20,6 +21,7 @@ - name: Ensure selfservice "Users can manage their own name details" is present ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: write attribute: @@ -32,6 +34,7 @@ - name: Ensure selfservice "Users can manage their own name details" is present again ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: write attribute: @@ -44,6 +47,7 @@ - name: Ensure selfservice "Users can manage their own name details" is present with different attribute initials ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: write attribute: @@ -54,6 +58,7 @@ - name: Ensure selfservice "Users can manage their own name details" is present with different attribute initials again ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: write attribute: @@ -64,6 +69,7 @@ - name: Ensure selfservice "Users can manage their own name details" member attributes givenname, displayname and title are present ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" attribute: - givenname @@ -76,6 +82,7 @@ - name: Ensure selfservice "Users can manage their own name details" member attributes givenname, displayname and title are present again ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" attribute: - givenname @@ -88,6 +95,7 @@ - name: Ensure selfservice "Users can manage their own name details" member attribute title is absent ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" attribute: - title @@ -99,6 +107,7 @@ - name: Ensure selfservice "Users can manage their own name details" member attribute title is absent again ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" attribute: - title @@ -112,6 +121,7 @@ - name: Ensure selfservice "Users can manage their own name details" is present with different read,write permission ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: read,write register: result @@ -120,6 +130,7 @@ - name: Ensure selfservice "Users can manage their own name details" is present with different read,write permission again ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: read,write register: result @@ -128,6 +139,7 @@ - name: Ensure selfservice "Users can manage their own name details" fails with bad permission read,read ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: read,read register: result @@ -136,6 +148,7 @@ - name: Ensure selfservice "Users can manage their own name details" fails with bad permission read,write,write ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" permission: read,write,write register: result @@ -144,6 +157,7 @@ - name: Ensure selfservice "Users can manage their own name details" fails with bad attribute title,title ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" attribute: - title @@ -156,5 +170,6 @@ - name: Ensure selfservice "Users can manage their own name details" is absent ipaselfservice: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: "Users can manage their own name details" state: absent diff --git a/tests/selfservice/test_selfservice_client_context.yml b/tests/selfservice/test_selfservice_client_context.yml new file mode 100644 index 00000000..d720aa53 --- /dev/null +++ b/tests/selfservice/test_selfservice_client_context.yml @@ -0,0 +1,37 @@ +--- +- name: Test selfservice + hosts: ipaclients, ipaserver + become: no + gather_facts: no + + tasks: + - name: Include FreeIPA facts. + include_tasks: ../env_freeipa_facts.yml + + # Test will only be executed if host is not a server. + - name: Execute with server context in the client. + ipaselfservice: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + register: result + failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*")) + when: ipa_host_is_client + +# Import basic module tests, and execute with ipa_context set to 'client'. +# If ipaclients is set, it will be executed using the client, if not, +# ipaserver will be used. +# +# With this setup, tests can be executed against an IPA client, against +# an IPA server using "client" context, and ensure that tests are executed +# in upstream CI. + +- name: Test selfservice using client context, in client host. + import_playbook: test_selfservice.yml + when: groups['ipaclients'] + vars: + ipa_test_host: ipaclients + +- name: Test selfservice using client context, in server host. + import_playbook: test_selfservice.yml + when: groups['ipaclients'] is not defined or not groups['ipaclients'] From d9dcc8f5dcfd5366d44eb4b4a0d8911363c7f5eb Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:46:15 -0300 Subject: [PATCH 31/32] topology: Allow execution of plugin in client host. Update README-topology.md file with details on support for new variable `ipaapi_context`. --- README-topology.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README-topology.md b/README-topology.md index 84ab240d..9391356b 100644 --- a/README-topology.md +++ b/README-topology.md @@ -159,11 +159,12 @@ 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 `suffix` | The topology suffix to be used, this can either be `domain`, `ca` or `domain+ca` | yes `name` \| `cn` | The topology segment name (cn) is the unique identifier for a segment. | no `left` \| `leftnode` | The left replication node string - an IPA server | no `right` \| `rightnode` | The right replication node string - an IPA server | no -`direction` | The direction a segment will be reinitialized. It can either be `left-to-right` or `right-to-left` and only used with `state: reinitialized` | +`direction` | The direction a segment will be reinitialized. It can either be `left-to-right` or `right-to-left` and only used with `state: reinitialized` | no `state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `checked` or `reinitialized` | yes @@ -176,6 +177,7 @@ 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 `suffix` | The topology suffix to be used, this can either be `domain` or `ca` | yes `state` | The state to ensure. It can only be `verified` | yes From 7e0624d8362671d59fc49e33f616a4ef29c5b114 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 3 Sep 2021 13:31:57 -0300 Subject: [PATCH 32/32] ipavault: Allow execution of plugin in client host. Update vault README file and add tests for executing plugin with `ipaapi_context` set to `client`. A new test playbook can be found at: tests/vault/test_vault_client_context.yml As `ipavault` only works in client context, an error is raised if it is explicitly executed in a server context. --- README-vault.md | 1 + plugins/modules/ipavault.py | 7 ++++++- tests/vault/env_cleanup.yml | 2 ++ tests/vault/env_setup.yml | 2 ++ tests/vault/test_vault_client_context.yml | 25 +++++++++++++++++++++++ 5 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/vault/test_vault_client_context.yml diff --git a/README-vault.md b/README-vault.md index 3f5f989e..545c343a 100644 --- a/README-vault.md +++ b/README-vault.md @@ -217,6 +217,7 @@ 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. Currently only `client` is supported by this module, and use of `server` will raise a failure. | no `name` \| `cn` | The list of vault name strings. | yes `description` | The vault description string. | no `password` \| `vault_password` \| `ipavaultpassword` \| `old_password`| Vault password. | no diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py index 7af6c353..abd5eddf 100644 --- a/plugins/modules/ipavault.py +++ b/plugins/modules/ipavault.py @@ -443,6 +443,11 @@ def check_parameters( # pylint: disable=unused-argument password, password_file, public_key, public_key_file, private_key, private_key_file, vault_data, datafile_in, datafile_out, new_password, new_password_file): + if module.params_get("ipaapi_context") == "server": + module.fail_json( + msg="Context 'server' for ipavault not yet supported." + ) + invalid = [] if state == "present": invalid = ['datafile_out'] @@ -718,7 +723,7 @@ def main(): changed = False exit_args = {} - with ansible_module.ipa_connect(context='ansible-freeipa') as ccache_name: + with ansible_module.ipa_connect(context="client") as ccache_name: if ccache_name is not None: os.environ["KRB5CCNAME"] = ccache_name diff --git a/tests/vault/env_cleanup.yml b/tests/vault/env_cleanup.yml index 9b0d6f7e..e545e791 100644 --- a/tests/vault/env_cleanup.yml +++ b/tests/vault/env_cleanup.yml @@ -26,6 +26,7 @@ - name: Ensure test users do not exist. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: - user01 - user02 @@ -35,6 +36,7 @@ - name: Ensure test groups do not exist. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: vaultgroup state: absent diff --git a/tests/vault/env_setup.yml b/tests/vault/env_setup.yml index 059caf5f..4e2d40e8 100644 --- a/tests/vault/env_setup.yml +++ b/tests/vault/env_setup.yml @@ -35,11 +35,13 @@ - name: Ensure vaultgroup exists. ipagroup: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" name: vaultgroup - name: Ensure testing users exist. ipauser: ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" users: - name: user01 first: First diff --git a/tests/vault/test_vault_client_context.yml b/tests/vault/test_vault_client_context.yml new file mode 100644 index 00000000..2ebb410e --- /dev/null +++ b/tests/vault/test_vault_client_context.yml @@ -0,0 +1,25 @@ +--- +- name: Test vault + hosts: ipaserver + become: no + # Need to gather facts for ansible_env. + gather_facts: yes + + tasks: + - name: Setup testing environment. + import_tasks: env_setup.yml + + # vault requires 'ipaapi_context: client', and uses this + # context by defoult, so we test only for the case where + # 'ipaapi_context: server' is explicitly set. + - name: Execute with server context. + ipavault: + ipaadmin_password: SomeADMINpassword + ipaapi_context: server + name: ThisShouldNotWork + vault_type: standard + register: result + failed_when: not (result.failed and result.msg is regex("Context 'server' for ipavault not yet supported.")) + + - name: Cleanup testing environment. + import_tasks: env_cleanup.yml