From 650f0c0d31545ea0da886de225f958de4c0b2400 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Tue, 20 Aug 2024 09:46:57 +1000 Subject: [PATCH 1/2] group - fix setting explicitly empty members Add a fix when attempting to create a group with an explicitly empty set of members. This fix also applies to any other add/set/remove attribute when the resulting value is an empty value. The error only applied when creating the AD object as the `New-AD* -OtherAttributes` parameter could not handle an empty array value. --- .../fragments/141-group-empty-member.yml | 4 + plugins/module_utils/_ADObject.psm1 | 7 +- .../integration/targets/group/tasks/tests.yml | 73 +++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/141-group-empty-member.yml diff --git a/changelogs/fragments/141-group-empty-member.yml b/changelogs/fragments/141-group-empty-member.yml new file mode 100644 index 0000000..0284fb9 --- /dev/null +++ b/changelogs/fragments/141-group-empty-member.yml @@ -0,0 +1,4 @@ +bugfixes: + - >- + group - fix error when creating a group with no members explicitly set - + https://github.com/ansible-collections/microsoft.ad/issues/141 diff --git a/plugins/module_utils/_ADObject.psm1 b/plugins/module_utils/_ADObject.psm1 index 693419a..1a3bd78 100644 --- a/plugins/module_utils/_ADObject.psm1 +++ b/plugins/module_utils/_ADObject.psm1 @@ -1253,7 +1253,9 @@ Function Invoke-AnsibleADObject { $propValue = $propValue | ConvertTo-AnsibleADDistinguishedName @adParams -Module $module -Context $propInfo.Name } - if ($propInfo.IsRawAttribute) { + # If the value is empty we don't want to explicitly set it + # as that will be the default and can fail if empty. + if ($propInfo.IsRawAttribute -and @($propValue).Count) { if (-not $newParams.ContainsKey('OtherAttributes')) { $newParams.OtherAttributes = @{} } @@ -1262,7 +1264,7 @@ Function Invoke-AnsibleADObject { # ForEach-Object to get back a vanilla object[] to set. $newParams.OtherAttributes[$propInfo.Attribute] = $propValue | ForEach-Object { "$_" } } - else { + elseif (-not $propInfo.IsRawAttribute) { $newParams[$propInfo.Attribute] = $propValue } @@ -1293,6 +1295,7 @@ Function Invoke-AnsibleADObject { $adObject = & $newCommand @newParams @adParams } catch { + $module.Result.zzz = $newParams # Using FailJson means other useful debugging information # like the diff output is returned $module.FailJson("New-$ModuleNoun failed: $_", $_) diff --git a/tests/integration/targets/group/tasks/tests.yml b/tests/integration/targets/group/tasks/tests.yml index c9cb7d8..21c7b79 100644 --- a/tests/integration/targets/group/tasks/tests.yml +++ b/tests/integration/targets/group/tasks/tests.yml @@ -409,6 +409,79 @@ that: - not remove_group_again is changed + - name: create group with empty members - check + group: + name: MyGroup + state: present + scope: domainlocal + members: + set: [] + register: group_empty_members_check + check_mode: true + + - name: get result of create group - check + object_info: + identity: '{{ group_empty_members_check.distinguished_name }}' + register: group_empty_members_check_actual + + - name: assert create group with empty members - check + assert: + that: + - group_empty_members_check is changed + - group_empty_members_check.distinguished_name == 'CN=MyGroup,CN=Users,' ~ setup_domain_info.output[0].defaultNamingContext + - group_empty_members_check.object_guid == '00000000-0000-0000-0000-000000000000' + - group_empty_members_check.sid == 'S-1-5-0000' + - group_empty_members_check_actual.objects == [] + + - name: create group with empty members + group: + name: MyGroup + state: present + scope: domainlocal + members: + set: [] + register: group_empty_members + + - set_fact: + object_identity: '{{ group_empty_members.object_guid }}' + + - name: get result of create group + object_info: + identity: '{{ group_empty_members.distinguished_name }}' + properties: + - member + - objectSid + register: group_empty_members_actual + + - name: assert create group with empty members + assert: + that: + - group_empty_members is changed + - group_empty_members.distinguished_name == 'CN=MyGroup,CN=Users,' ~ setup_domain_info.output[0].defaultNamingContext + - group_empty_members_actual.objects | length == 1 + - group_empty_members.object_guid == group_empty_members_actual.objects[0].ObjectGUID + - group_empty_members.sid == group_empty_members_actual.objects[0].objectSid.Sid + - group_empty_members_actual.objects[0].member == None + + - name: create group with empty members - idempotent + group: + name: MyGroup + state: present + scope: domainlocal + members: + set: [] + register: group_empty_members_again + + - name: assert create group with empty members - idempotent + assert: + that: + - not group_empty_members_again is changed + + - name: remove group for next steps + group: + name: MyGroup + state: absent + - name: fail to create group with invalid members group: name: MyGroup From b2afdf4eaf2acdd20f02dd50b08f7eb499c97823 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Wed, 21 Aug 2024 04:14:19 +1000 Subject: [PATCH 2/2] Remove debugging line --- plugins/module_utils/_ADObject.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/module_utils/_ADObject.psm1 b/plugins/module_utils/_ADObject.psm1 index 1a3bd78..a79cd10 100644 --- a/plugins/module_utils/_ADObject.psm1 +++ b/plugins/module_utils/_ADObject.psm1 @@ -1295,7 +1295,6 @@ Function Invoke-AnsibleADObject { $adObject = & $newCommand @newParams @adParams } catch { - $module.Result.zzz = $newParams # Using FailJson means other useful debugging information # like the diff output is returned $module.FailJson("New-$ModuleNoun failed: $_", $_)