From 3c8d6c7c7aec408b3b68440982929e30e7d69130 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Mon, 5 Sep 2022 17:18:00 -0300 Subject: [PATCH] ipaconfig: Add support for SID related attributes. Since FreeIPA 4.9.8 the 'config_mod' command has parameters to enable and configure SIDs, and set the Netbios name. This patch adds the following parameters to ipaconfig plugin: enable_sids: New users and groups automatically get a SID assigned add_sids: Add SIDs for existing users and groups netbios_name: NetBIOS name of the IPA domain Both add_sids and netbios_name requires 'enable_sid: yes'. 'enable_sid' and 'netbios_name' are returned when querying IPA configuration. 'add_sids' always generate SIDs for users and groups, so, muiltiple executions of the playbook with 'add_sids: yes' will return 'changed', even if users and groups SIDs are not modified. A new test playbook is available: tests/config/test_config_sid.yml New examples playbooks are available: playbooks/config/change-ipa-domain-netbios-name.yml playbooks/config/generate-users-groups-sids.yml Fixes: #781 Related: https://bugzilla.redhat.com/show_bug.cgi?id=2069174 Related: https://bugzilla.redhat.com/show_bug.cgi?id=2069184 --- README-config.md | 42 ++++++ .../config/change-ipa-domain-netbios-name.yml | 12 ++ .../config/generate-users-groups-sids.yml | 12 ++ plugins/modules/ipaconfig.py | 120 +++++++++++++++++- tests/azure/templates/variables_centos-7.yaml | 9 +- tests/config/test_config_sid.yml | 70 ++++++++++ 6 files changed, 256 insertions(+), 9 deletions(-) create mode 100644 playbooks/config/change-ipa-domain-netbios-name.yml create mode 100644 playbooks/config/generate-users-groups-sids.yml create mode 100644 tests/config/test_config_sid.yml diff --git a/README-config.md b/README-config.md index 17c85f1..13023ea 100644 --- a/README-config.md +++ b/README-config.md @@ -65,6 +65,9 @@ Example playbook to read config options: maxusername: 64 ``` + +Example playbook to set global configuration options: + ```yaml --- - name: Playbook to ensure some config options are set @@ -79,6 +82,40 @@ Example playbook to read config options: ``` +Example playbook to enable SID and generate users and groups SIDs: + +```yaml +--- +- name: Playbook to ensure SIDs are enabled and users and groups have SIDs + hosts: ipaserver + become: no + gather_facts: no + + tasks: + - name: Enable SID and generate users and groups SIDS + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_sid: yes + add_sids: yes +``` + +Example playbook to change IPA domain NetBIOS name: + +```yaml +--- +- name: Playbook to change IPA domain netbios name + hosts: ipaserver + become: no + gather_facts: no + + tasks: + - name: Set IPA domain netbios name + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_sid: yes + netbios_name: IPADOM +``` + Variables ========= @@ -111,6 +148,9 @@ Variable | Description | Required `user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `disabled`). Use `""` to clear this variable. | no `domain_resolution_order` \| `ipadomainresolutionorder` | Set list of domains used for short name qualification | no `ca_renewal_master_server` \| `ipacarenewalmasterserver`| Renewal master for IPA certificate authority. | no +`enable_sid` | New users and groups automatically get a SID assigned. Requires IPA 4.9.8+. (bool) | no +`netbios_name` | NetBIOS name of the IPA domain. Requires IPA 4.9.8+ and 'enable_sid: yes'. | no +`add_sids` | Add SIDs for existing users and groups. Requires IPA 4.9.8+ and 'enable_sid: yes'. (bool) | no Return Values @@ -140,6 +180,8 @@ Variable | Description | Returned When   | `user_auth_type` |     | `domain_resolution_order` |     | `ca_renewal_master_server` |   +  | `enable_sid` |   +  | `netbios_name` |   All returned fields take the same form as their namesake input parameters diff --git a/playbooks/config/change-ipa-domain-netbios-name.yml b/playbooks/config/change-ipa-domain-netbios-name.yml new file mode 100644 index 0000000..04e56b3 --- /dev/null +++ b/playbooks/config/change-ipa-domain-netbios-name.yml @@ -0,0 +1,12 @@ +--- +- name: Playbook to change IPA domain netbios name + hosts: ipaserver + become: no + gather_facts: no + + tasks: + - name: Set IPA domain netbios name + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_sid: yes + netbios_name: IPADOM diff --git a/playbooks/config/generate-users-groups-sids.yml b/playbooks/config/generate-users-groups-sids.yml new file mode 100644 index 0000000..9df85ba --- /dev/null +++ b/playbooks/config/generate-users-groups-sids.yml @@ -0,0 +1,12 @@ +--- +- name: Playbook to ensure SIDs are enabled and users and groups have SIDs + hosts: ipaserver + become: no + gather_facts: no + + tasks: + - name: Enable SID and generate users and groups SIDS + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_sid: yes + add_sids: yes diff --git a/plugins/modules/ipaconfig.py b/plugins/modules/ipaconfig.py index 6731e37..d1f1398 100644 --- a/plugins/modules/ipaconfig.py +++ b/plugins/modules/ipaconfig.py @@ -148,6 +148,24 @@ options: required: false type: list aliases: ["ipadomainresolutionorder"] + enable_sid: + description: > + New users and groups automatically get a SID assigned. + Requires IPA 4.9.8+. + required: false + type: bool + netbios_name: + description: > + NetBIOS name of the IPA domain. + Requires IPA 4.9.8+ and 'enable_sid: yes'. + required: false + type: string + add_sids: + description: > + Add SIDs for existing users and groups. + Requires IPA 4.9.8+ and 'enable_sid: yes'. + required: false + type: bool ''' EXAMPLES = ''' @@ -169,6 +187,24 @@ EXAMPLES = ''' ipaadmin_password: SomeADMINpassword defaultshell: /bin/bash maxusername: 64 + +- name: Playbook to enable SID and generate users and groups SIDs + hosts: ipaserver + tasks: + - name: Enable SID and generate users and groups SIDS + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_sid: yes + add_sids: yes + +- name: Playbook to change IPA domain netbios name + hosts: ipaserver + tasks: + - name: Enable SID and generate users and groups SIDS + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_sid: yes + netbios_name: IPADOM ''' RETURN = ''' @@ -247,6 +283,14 @@ config: domain_resolution_order: description: list of domains used for short name qualification returned: always + enable_sid: + description: > + new users and groups automatically get a SID assigned. + Requires IPA 4.9.8+. + returned: always + netbios_name: + description: NetBIOS name of the IPA domain. Requires IPA 4.9.8+. + returned: if enable_sid is True ''' @@ -260,6 +304,28 @@ def config_show(module): return _result["result"] +def get_netbios_name(module): + try: + _result = module.ipa_command_no_name("trustconfig_show", {"all": True}) + except Exception: # pylint: disable=broad-except + return None + else: + return _result["result"]["ipantflatname"][0] + + +def is_enable_sid(module): + """When 'enable-sid' is true admin user and admins group have SID set.""" + _result = module.ipa_command("user_show", "admin", {"all": True}) + sid = _result["result"].get("ipantsecurityidentifier", [""]) + if not sid[0].endswith("-500"): + return False + _result = module.ipa_command("group_show", "admins", {"all": True}) + sid = _result["result"].get("ipantsecurityidentifier", [""]) + if not sid[0].endswith("-512"): + return False + return True + + def main(): ansible_module = IPAAnsibleModule( argument_spec=dict( @@ -313,7 +379,10 @@ def main(): aliases=["ipauserauthtype"]), ca_renewal_master_server=dict(type="str", required=False), domain_resolution_order=dict(type="list", required=False, - aliases=["ipadomainresolutionorder"]) + aliases=["ipadomainresolutionorder"]), + enable_sid=dict(type="bool", required=False), + add_sids=dict(type="bool", required=False), + netbios_name=dict(type="str", required=False), ), supports_check_mode=True, ) @@ -344,7 +413,10 @@ def main(): "pac_type": "ipakrbauthzdata", "user_auth_type": "ipauserauthtype", "ca_renewal_master_server": "ca_renewal_master_server", - "domain_resolution_order": "ipadomainresolutionorder" + "domain_resolution_order": "ipadomainresolutionorder", + "enable_sid": "enable_sid", + "netbios_name": "netbios_name", + "add_sids": "add_sids", } allow_empty_string = ["pac_type", "user_auth_type", "configstring"] reverse_field_map = {v: k for k, v in field_map.items()} @@ -394,11 +466,47 @@ def main(): changed = False exit_args = {} - # Connect to IPA API - with ansible_module.ipa_connect(): + # Connect to IPA API (enable-sid requires context == 'client') + with ansible_module.ipa_connect(context="client"): + has_enable_sid = ansible_module.ipa_command_param_exists( + "config_mod", "enable_sid") result = config_show(ansible_module) + if params: + netbios_name = params.get("netbios_name") + if netbios_name: + netbios_name = netbios_name.upper() + add_sids = params.get("add_sids") + enable_sid = params.get("enable_sid") + required_sid = any([netbios_name, add_sids]) + if required_sid and not enable_sid: + ansible_module.fail_json( + "'enable-sid: yes' required for 'netbios_name' " + "and 'add-sids'." + ) + if enable_sid: + if not has_enable_sid: + ansible_module.fail_json( + "This version of IPA does not support 'enable-sid'.") + if ( + netbios_name + and netbios_name == get_netbios_name(ansible_module) + ): + del params["netbios_name"] + netbios_name = None + if not add_sids and "add_sids" in params: + del params["add_sids"] + if ( + not any([netbios_name, add_sids]) + and is_enable_sid(ansible_module) + ): + del params["enable_sid"] + else: + for param in ["enable_sid", "netbios_name", "add_sids"]: + if param in params: + del params[params] + params = { k: v for k, v in params.items() if k not in result or result[k] != v @@ -458,6 +566,10 @@ def main(): # Add empty domain_resolution_order if it is not set if "domain_resolution_order" not in exit_args: exit_args["domain_resolution_order"] = [] + # Set enable_sid + if has_enable_sid: + exit_args["enable_sid"] = is_enable_sid(ansible_module) + exit_args["netbios_name"] = get_netbios_name(ansible_module) # Done ansible_module.exit_json(changed=changed, config=exit_args) #diff --git a/tests/azure/templates/variables_centos-7.yaml b/tests/azure/templates/variables_centos-7.yaml #index 586d5ec..8628af2 100644 #--- a/tests/azure/templates/variables_centos-7.yaml #+++ b/tests/azure/templates/variables_centos-7.yaml #@@ -12,8 +12,7 @@ # # # --- # variables: #- empty: true #-# ipa_enabled_modules: >- #-# ipa_enabled_tests: >- #-# ipa_disabled_modules: >- #-# ipa_disabled_tests: >- #+ # ipa_enabled_modules: >- #+ # ipa_enabled_tests: >- #+ # ipa_disabled_modules: >- #+ ipa_disabled_tests: test_config_sid diff --git a/tests/config/test_config_sid.yml b/tests/config/test_config_sid.yml new file mode 100644 index 0000000..1761795 --- /dev/null +++ b/tests/config/test_config_sid.yml @@ -0,0 +1,70 @@ +--- +- name: Test config + hosts: "{{ ipa_test_host | default('ipaserver') }}" + become: no + gather_facts: no + + tasks: + + # GET CURRENT CONFIG + + - name: Return current values of the global configuration options + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + register: previous + + # TESTS + - block: + - name: Ensure SID is enabled. + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + enable_sid: yes + register: result + failed_when: result.failed or previous.config.enable_sid == result.changed + + - name: Ensure SID is enabled, again. + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + enable_sid: yes + register: result + failed_when: result.failed or result.changed + + - name: Ensure netbios_name is "IPATESTPLAY" + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + enable_sid: yes + netbios_name: IPATESTPLAY + register: result + failed_when: result.failed or not result.changed + + - name: Ensure netbios_name is "IPATESTPLAY", again + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + enable_sid: yes + netbios_name: IPATESTPLAY + register: result + failed_when: result.failed or result.changed + + # add_sids is not idempotent as it always tries to generate the missing + # SIDs for users and groups. + - name: Add SIDs to users and groups. + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + enable_sid: yes + add_sids: yes + + # REVERT TO PREVIOUS CONFIG + always: + # Once SID is enabled, it cannot be reverted. + - name: Revert netbios_name to original configuration + ipaconfig: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + netbios_name: "{{ previous.config.netbios_name | default(omit) }}" + enable_sid: yes -- 2.37.3