Active Directory Group Membership

I’ve written some simple terraform code to assist with creating group membership for active directory groups. This is an on-prem deployment of Active Directory and we are using the hashicorp/ad provider.

Expected Behavior
When apply is run, the code will be checked against the state file and add, change or destroy objects determined, and actioned, accordingly. In addition, if the code matches the state file, it will report as such with no prompt to confirm an action.

Actual Behavior
Each time the apply is run, group membership is changed. When I add a member to the group, all existing members are removed and the new member added. If I make no changes to membership, all members are removed and, if I apply again without change, all members are added.

Has anyone else experienced this behavior?
Can anyone explain this behavior, is something in my code causing this?

terraform {
  required_version = ">= 0.14.0"
  required_providers {
    ad = {
      source = "hashicorp/ad"
      version = "0.4.4"
    }
  }
}

provider "ad" {
  winrm_hostname = "hostname"
  winrm_username = "username"
  winrm_password = "password"
}

variable group_memberships {
  type = map(object({
    user_list     = list(string)
    group_list    = list(string)
    computer_list = list(string)
  }))
}

group_memberships = {
  AppAccessGroup = {
    user_list     = [
                    "roger.ramjet",
                    "wylie.coyote"]
    group_list    = [
                    "ReadOnlyUsers",
                    "TemporaryUsers"]
    computer_list = [
                    "computer01$",
                    "computer02$"]
  }
}

resource ad_group_membership "gm" {
  for_each = var.group_memberships 
    group_id = each.key
    group_members  = concat(each.value.user_list, each.value.group_list, each.value.computer_list)
}

I did some more investigation and found the answer.

The ad_group_membership resource is very flexible when specifying a list of member AD Principals. From the provider documentation:
“Each principal can be identified by its GUID, SID, Distinguished Name, or SAM Account Name. Only one is required”

This makes it easy to create the membership resource, as you can see in the code I posted.

The problem is, the provider records the list of principals in the state file using each principal’s ID (GUID):

    {
      "mode": "managed",
      "type": "ad_group_membership",
      "name": "gm",
      "provider": "provider[\"registry.terraform.io/hashicorp/ad\"]",
      "instances": [
        {
          "index_key": "AppAccessGroup",
          "schema_version": 0,
          "attributes": {
            "group_id": "AppAccessGroup",
            "group_members": [
              "071792bd-1e5b-4ff5-a57a-969bee712b08",
              "22ee22ba-c562-4645-b03a-1ce451c925f1",
              "2cd6fbcc-5ce2-4e77-95c4-d4a56eb2c974",
              "db274f67-0360-4d6f-9daf-027065dea943",
              "f6655ffc-97d8-4243-851f-7b709d671ec3"
            ],
            "id": "AppAccessGroup_9efccf37-c6cf-f1fd-9f99-9797b23d8cd9"
          },
          "sensitive_attributes": [],
          "private": "bnVsbA==",
          "dependencies": [
            "data.ad_computer.c",
            "data.ad_group.g",
            "data.ad_user.u"
          ]
        }
      ]
    }

So every time the code is applied, the resource is destroyed because it does not have any matching members.

To avoid this problem, the principals should be specified with their GUID, rather than Distinguished Name or SAM Account Name. So, the code gets more complex to keep descriptive names (for readability) and fetch the respective IDs for the resource block.

Ran into the same problem today. I forked the provider and added an option for configuring which attribute to use for ad_group_membership. My use-case involves creating users dynamically and also populating groups dynamically and since the objectGUID is not known beforehand this made it impossible, but with my own fork it works.

Feel free to use it.

1 Like

Hi, I’ve also just rum across the same issue. It also makes it incredibly slow to apply, as I’ve over a hundred groups referenced by name, not GUID. I don’t suppose you’ve thought about creating an issue and PR to push it upstream? :slightly_smiling_face:

Alex,

I have not created an issue, nor pushed anything upstream.

My project was put on hold, so I have not put anymore effort into this specific problem.

If this changes I probably will create and issue with Hashi.

Regards,

Hi Roy, thanks for your quick reply. I only just saw it, after going through open tabs on my phone to close. (Need to look for notification settings I suppose).

I did find a PR created by a Yrix90, which addresses the problem by adding a “membership_attribute” option to the configuration. I thought it was yours actually!

Anyway, I’ve had my own stab at hacking the ad_group_membership code in the hashicorp/ad provider, so now any attribute can be specified in the group_members list. I put a PR up at:-

Maybe it will help someone else. (I’ll try and figure out how to publish it to terraform.io for anyone else to use, as upstream looks fairly abandoned?).

Cheers,
Alex