Skip to content

Commit c0cea8b

Browse files
committed
Adding new resource to manage group LDAP links. Includes acceptance tests and a test data template for defining real LDAP data.
1 parent 81bb2ec commit c0cea8b

File tree

4 files changed

+420
-0
lines changed

4 files changed

+420
-0
lines changed

gitlab/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func Provider() terraform.ResourceProvider {
8484
"gitlab_service_jira": resourceGitlabServiceJira(),
8585
"gitlab_project_share_group": resourceGitlabProjectShareGroup(),
8686
"gitlab_group_cluster": resourceGitlabGroupCluster(),
87+
"gitlab_group_ldap_link": resourceGitlabGroupLdapLink(),
8788
},
8889

8990
ConfigureFunc: providerConfigure,
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package gitlab
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"log"
7+
"strings"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
10+
gitlab "github.com/xanzy/go-gitlab"
11+
)
12+
13+
func resourceGitlabGroupLdapLink() *schema.Resource {
14+
acceptedAccessLevels := make([]string, 0, len(accessLevelID))
15+
for k := range accessLevelID {
16+
acceptedAccessLevels = append(acceptedAccessLevels, k)
17+
}
18+
return &schema.Resource{
19+
Create: resourceGitlabGroupLdapLinkCreate,
20+
Read: resourceGitlabGroupLdapLinkRead,
21+
Delete: resourceGitlabGroupLdapLinkDelete,
22+
23+
Schema: map[string]*schema.Schema{
24+
"group_id": {
25+
Type: schema.TypeString,
26+
Required: true,
27+
ForceNew: true,
28+
},
29+
"cn": {
30+
Type: schema.TypeString,
31+
Required: true,
32+
ForceNew: true,
33+
},
34+
// Using the friendlier "access_level" here instead of the GitLab API "group_access".
35+
"access_level": {
36+
Type: schema.TypeString,
37+
ValidateFunc: validateValueFunc(acceptedAccessLevels),
38+
Required: true,
39+
ForceNew: true,
40+
},
41+
// Changing GitLab API parameter "provider" to "ldap_provider" to avoid clashing with the Terraform "provider" key word
42+
"ldap_provider": {
43+
Type: schema.TypeString,
44+
Required: true,
45+
ForceNew: true,
46+
},
47+
"force": {
48+
Type: schema.TypeBool,
49+
Optional: true,
50+
Default: false,
51+
ForceNew: true,
52+
},
53+
},
54+
}
55+
}
56+
57+
func resourceGitlabGroupLdapLinkCreate(d *schema.ResourceData, meta interface{}) error {
58+
client := meta.(*gitlab.Client)
59+
60+
groupId := d.Get("group_id").(string)
61+
cn := d.Get("cn").(string)
62+
group_access := int(accessLevelNameToValue[d.Get("access_level").(string)])
63+
ldap_provider := d.Get("ldap_provider").(string)
64+
force := d.Get("force").(bool)
65+
66+
options := &gitlab.AddGroupLDAPLinkOptions{
67+
CN: &cn,
68+
GroupAccess: &group_access,
69+
Provider: &ldap_provider,
70+
}
71+
72+
if force {
73+
resourceGitlabGroupLdapLinkDelete(d, meta)
74+
}
75+
76+
log.Printf("[DEBUG] Create GitLab group LdapLink %s", d.Id())
77+
LdapLink, _, err := client.Groups.AddGroupLDAPLink(groupId, options)
78+
if err != nil {
79+
return err
80+
}
81+
82+
d.SetId(buildTwoPartID(&LdapLink.Provider, &LdapLink.CN))
83+
84+
return resourceGitlabGroupLdapLinkRead(d, meta)
85+
}
86+
87+
func resourceGitlabGroupLdapLinkRead(d *schema.ResourceData, meta interface{}) error {
88+
client := meta.(*gitlab.Client)
89+
groupId := d.Get("group_id").(string)
90+
91+
// Try to fetch all group links from GitLab
92+
log.Printf("[DEBUG] Read GitLab group LdapLinks %s", groupId)
93+
ldapLinks, _, err := client.Groups.ListGroupLDAPLinks(groupId, nil)
94+
if err != nil {
95+
// The read/GET API wasn't implemented in GitLab until version 12.8 (March 2020, well after the add and delete APIs).
96+
// If we 404, assume GitLab is at an older version and take things on faith.
97+
switch err.(type) {
98+
case *gitlab.ErrorResponse:
99+
if err.(*gitlab.ErrorResponse).Response.StatusCode == 404 {
100+
log.Printf("[WARNING] This GitLab instance doesn't have the GET API for group_ldap_sync. Please upgrade to 12.8 or later for best results.")
101+
} else {
102+
return err
103+
}
104+
default:
105+
return err
106+
}
107+
}
108+
109+
// If we got here and don't have links, assume GitLab is below version 12.8 and skip the check
110+
if ldapLinks != nil {
111+
// Check if the LDAP link exists in the returned list of links
112+
found := false
113+
for _, ldapLink := range ldapLinks {
114+
if buildTwoPartID(&ldapLink.Provider, &ldapLink.CN) == d.Id() {
115+
d.Set("group_id", groupId)
116+
d.Set("cn", ldapLink.CN)
117+
d.Set("group_access", ldapLink.GroupAccess)
118+
d.Set("ldap_provider", ldapLink.Provider)
119+
found = true
120+
break
121+
}
122+
}
123+
124+
if !found {
125+
d.SetId("")
126+
return errors.New(fmt.Sprintf("LdapLink %s does not exist.", d.Id()))
127+
}
128+
}
129+
130+
return nil
131+
}
132+
133+
func resourceGitlabGroupLdapLinkDelete(d *schema.ResourceData, meta interface{}) error {
134+
client := meta.(*gitlab.Client)
135+
groupId := d.Get("group_id").(string)
136+
cn := d.Get("cn").(string)
137+
ldap_provider := d.Get("ldap_provider").(string)
138+
139+
log.Printf("[DEBUG] Delete GitLab group LdapLink %s", d.Id())
140+
_, err := client.Groups.DeleteGroupLDAPLinkForProvider(groupId, ldap_provider, cn)
141+
if err != nil {
142+
switch err.(type) {
143+
case *gitlab.ErrorResponse:
144+
// Ignore LDAP links that don't exist
145+
if strings.Contains(string(err.(*gitlab.ErrorResponse).Message), "Linked LDAP group not found") {
146+
log.Printf("[WARNING] %s", err)
147+
} else {
148+
return err
149+
}
150+
default:
151+
return err
152+
}
153+
}
154+
155+
return nil
156+
}

0 commit comments

Comments
 (0)