From e2c47da9595aad27a9c5926d2df40e1e0686c3ef Mon Sep 17 00:00:00 2001 From: Oliver Isaac Date: Mon, 8 Feb 2021 16:12:20 -0600 Subject: [PATCH 1/3] Added skip_attributes resource definition to allow ignoring attributes set by Windows AD --- provider/resource_ldap_object.go | 35 +++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/provider/resource_ldap_object.go b/provider/resource_ldap_object.go index ce6ecf2..46b3c58 100644 --- a/provider/resource_ldap_object.go +++ b/provider/resource_ldap_object.go @@ -60,6 +60,13 @@ func resourceLDAPObject() *schema.Resource { }, Optional: true, }, + "skip_attributes": { + Type: schema.TypeSet, + Description: "A list of attributes which will not be tracked by the provider", + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Optional: true, + }, }, } } @@ -118,6 +125,13 @@ func resourceLDAPObjectCreate(d *schema.ResourceData, meta interface{}) error { } request.Attribute("objectClass", objectClasses) + // retrieve attributes to skip from HCL + attributesToSkip := []string{"objectClass"} + for _, attr := range (d.Get("skip_attributes").(*schema.Set)).List() { + log.Printf("[DEBUG] ldap_object::create - object %q set to skip: %q", dn, attr.(string)) + attributesToSkip = append(attributesToSkip, attr.(string)) + } + // if there is a non empty list of attributes, loop though it and // create a new map collecting attribute names and its value(s); we need to // do this because we could not model the attributes as a map[string][]string @@ -133,6 +147,9 @@ func resourceLDAPObjectCreate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] ldap_object::create - %q has attribute of type %T", dn, attribute) // each map should only have one entry (see resource declaration) for name, value := range attribute.(map[string]interface{}) { + if stringSliceContains(attributesToSkip, name) { + continue + } log.Printf("[DEBUG] ldap_object::create - %q has attribute[%v] => %v (%T)", dn, name, value, value) v := toAttributeValue(name, value.(string)) m[name] = append(m[name], v) @@ -156,6 +173,15 @@ func resourceLDAPObjectCreate(d *schema.ResourceData, meta interface{}) error { return resourceLDAPObjectRead(d, meta) } +func stringSliceContains(haystack []string, needle string) bool { + for _, h := range haystack { + if needle == h { + return true + } + } + return false +} + func resourceLDAPObjectRead(d *schema.ResourceData, meta interface{}) error { return readLDAPObject(d, meta, true) } @@ -254,6 +280,13 @@ func readLDAPObject(d *schema.ResourceData, meta interface{}, updateState bool) d.SetId(dn) d.Set("object_classes", sr.Entries[0].GetAttributeValues("objectClass")) + // retrieve attributes to skip from HCL + attributesToSkip := []string{"objectClass"} + for _, attr := range (d.Get("skip_attributes").(*schema.Set)).List() { + log.Printf("[DEBUG] ldap_object::create - object %q set to skip: %q", dn, attr.(string)) + attributesToSkip = append(attributesToSkip, attr.(string)) + } + // now deal with attributes set := &schema.Set{ F: attributeHash, @@ -261,7 +294,7 @@ func readLDAPObject(d *schema.ResourceData, meta interface{}, updateState bool) for _, attribute := range sr.Entries[0].Attributes { log.Printf("[DEBUG] ldap_object::read - treating attribute %q of %q (%d values: %v)", attribute.Name, dn, len(attribute.Values), attribute.Values) - if attribute.Name == "objectClass" { + if stringSliceContains(attributesToSkip, attribute.Name) { // skip: we don't treat object classes as ordinary attributes log.Printf("[DEBUG] ldap_object::read - skipping attribute %q of %q", attribute.Name, dn) continue From a0c05764d8a0572f0c2dd9e0ab62e6601f188a5c Mon Sep 17 00:00:00 2001 From: Oliver Isaac Date: Mon, 8 Feb 2021 16:13:56 -0600 Subject: [PATCH 2/3] index on add-skip-attributes: e2c47da Added skip_attributes resource definition to allow ignoring attributes set by Windows AD From 524b0d1192fa8f8d07698f2f948dab3afc6f5669 Mon Sep 17 00:00:00 2001 From: Oliver Isaac Date: Mon, 8 Feb 2021 16:43:48 -0600 Subject: [PATCH 3/3] Added option to set only the fields we care about. --- provider/resource_ldap_object.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/provider/resource_ldap_object.go b/provider/resource_ldap_object.go index 46b3c58..c244a33 100644 --- a/provider/resource_ldap_object.go +++ b/provider/resource_ldap_object.go @@ -67,6 +67,13 @@ func resourceLDAPObject() *schema.Resource { Set: schema.HashString, Optional: true, }, + "select_attributes": { + Type: schema.TypeSet, + Description: "Only attributes in this list will be modified by the provider", + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Optional: true, + }, }, } } @@ -132,6 +139,13 @@ func resourceLDAPObjectCreate(d *schema.ResourceData, meta interface{}) error { attributesToSkip = append(attributesToSkip, attr.(string)) } + // retrieve attributes to skip from HCL + attributesToSet := []string{} + for _, attr := range (d.Get("select_attributes").(*schema.Set)).List() { + log.Printf("[DEBUG] ldap_object::create - object %q set to only modify: %q", dn, attr.(string)) + attributesToSet = append(attributesToSet, attr.(string)) + } + // if there is a non empty list of attributes, loop though it and // create a new map collecting attribute names and its value(s); we need to // do this because we could not model the attributes as a map[string][]string @@ -150,6 +164,10 @@ func resourceLDAPObjectCreate(d *schema.ResourceData, meta interface{}) error { if stringSliceContains(attributesToSkip, name) { continue } + if len(attributesToSet) > 0 && !stringSliceContains(attributesToSet, name) { + log.Printf("[DEBUG] ldap_object::create - %q skipping unselected attribute", dn, name) + continue + } log.Printf("[DEBUG] ldap_object::create - %q has attribute[%v] => %v (%T)", dn, name, value, value) v := toAttributeValue(name, value.(string)) m[name] = append(m[name], v) @@ -287,6 +305,13 @@ func readLDAPObject(d *schema.ResourceData, meta interface{}, updateState bool) attributesToSkip = append(attributesToSkip, attr.(string)) } + // retrieve attributes to set from HCL + attributesToSet := []string{} + for _, attr := range (d.Get("select_attributes").(*schema.Set)).List() { + log.Printf("[DEBUG] ldap_object::create - object %q set to only modify: %q", dn, attr.(string)) + attributesToSet = append(attributesToSet, attr.(string)) + } + // now deal with attributes set := &schema.Set{ F: attributeHash, @@ -299,6 +324,10 @@ func readLDAPObject(d *schema.ResourceData, meta interface{}, updateState bool) log.Printf("[DEBUG] ldap_object::read - skipping attribute %q of %q", attribute.Name, dn) continue } + if len(attributesToSet) > 0 && !stringSliceContains(attributesToSet, attribute.Name) { + log.Printf("[DEBUG] ldap_object::read - skipping unselected attribute %q of %q", attribute.Name, dn) + continue + } if len(attribute.Values) == 1 { // we don't treat the RDN as an ordinary attribute a := fmt.Sprintf("%s=%s", attribute.Name, attribute.Values[0])