Skip to content

Commit 8b59900

Browse files
feat: Ldap Service (#43)
1 parent 742a728 commit 8b59900

File tree

3 files changed

+208
-0
lines changed

3 files changed

+208
-0
lines changed

client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Client struct {
4242
Config ConfigService
4343
Finding FindingService
4444
Event EventService
45+
LDAP LDAPService
4546
License LicenseService
4647
Metrics MetricsService
4748
OIDC OIDCService
@@ -91,6 +92,7 @@ func NewClient(baseURL string, options ...ClientOption) (*Client, error) {
9192
client.Config = ConfigService{client: &client}
9293
client.Finding = FindingService{client: &client}
9394
client.Event = EventService{client: &client}
95+
client.LDAP = LDAPService{client: &client}
9496
client.License = LicenseService{client: &client}
9597
client.Metrics = MetricsService{client: &client}
9698
client.OIDC = OIDCService{client: &client}

ldap.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package dtrack
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/google/uuid"
9+
)
10+
11+
type LDAPService struct {
12+
client *Client
13+
}
14+
15+
type LdapUser struct {
16+
Username string `json:"username,omitempty"`
17+
DistinguishedName string `json:"dn,omitempty"`
18+
Teams []Team `json:"teams,omitempty"`
19+
Email string `json:"email,omitempty"`
20+
Permissions []Permission `json:"permissions,omitempty"`
21+
}
22+
23+
type MappedLdapGroupRequest struct {
24+
Team uuid.UUID `json:"team"`
25+
DistinguishedName string `json:"dn"`
26+
}
27+
28+
type MappedLdapGroup struct {
29+
DistinguishedName string `json:"dn,omitempty"`
30+
UUID uuid.UUID `json:"uuid"`
31+
}
32+
33+
func (s LDAPService) AddMapping(ctx context.Context, mapping MappedLdapGroupRequest) (g MappedLdapGroup, err error) {
34+
req, err := s.client.newRequest(ctx, http.MethodPut, "/api/v1/ldap/mapping", withBody(mapping))
35+
if err != nil {
36+
return
37+
}
38+
39+
_, err = s.client.doRequest(req, &g)
40+
return
41+
}
42+
43+
func (s LDAPService) RemoveMapping(ctx context.Context, mappingId uuid.UUID) (err error) {
44+
req, err := s.client.newRequest(ctx, http.MethodDelete, fmt.Sprintf("/api/v1/ldap/mapping/%s", mappingId.String()))
45+
if err != nil {
46+
return
47+
}
48+
49+
_, err = s.client.doRequest(req, nil)
50+
return
51+
}
52+
53+
func (s LDAPService) GetAllAccessibleGroups(ctx context.Context, po PageOptions) (gs Page[string], err error) {
54+
req, err := s.client.newRequest(ctx, http.MethodGet, "/api/v1/ldap/groups", withPageOptions(po))
55+
if err != nil {
56+
return
57+
}
58+
59+
res, err := s.client.doRequest(req, &gs.Items)
60+
gs.TotalCount = res.TotalCount
61+
return
62+
}
63+
64+
func (s LDAPService) GetTeamMappings(ctx context.Context, teamUUID uuid.UUID) (gs []MappedLdapGroup, err error) {
65+
req, err := s.client.newRequest(ctx, http.MethodGet, fmt.Sprintf("/api/v1/ldap/team/%s", teamUUID.String()))
66+
if err != nil {
67+
return
68+
}
69+
70+
_, err = s.client.doRequest(req, &gs)
71+
return
72+
}
73+
74+
func (s LDAPService) GetUsers(ctx context.Context, po PageOptions) (us Page[LdapUser], err error) {
75+
req, err := s.client.newRequest(ctx, http.MethodGet, "/api/v1/user/ldap", withPageOptions(po))
76+
if err != nil {
77+
return
78+
}
79+
80+
res, err := s.client.doRequest(req, &us.Items)
81+
us.TotalCount = res.TotalCount
82+
return
83+
}
84+
85+
func (s LDAPService) CreateUser(ctx context.Context, user LdapUser) (userOut LdapUser, err error) {
86+
req, err := s.client.newRequest(ctx, http.MethodPut, "/api/v1/user/ldap", withBody(user))
87+
if err != nil {
88+
return
89+
}
90+
91+
_, err = s.client.doRequest(req, &userOut)
92+
return
93+
}
94+
95+
func (s LDAPService) DeleteUser(ctx context.Context, user LdapUser) (err error) {
96+
req, err := s.client.newRequest(ctx, http.MethodDelete, "/api/v1/user/ldap", withBody(user))
97+
if err != nil {
98+
return
99+
}
100+
101+
_, err = s.client.doRequest(req, nil)
102+
return
103+
}

ldap_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package dtrack
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestLdapMappings(t *testing.T) {
11+
// 1. Confirm absence of mappings
12+
// 2. Add mapping
13+
// 3. Confirm presence of mapping
14+
// 4. Remove mapping
15+
// 5. Confirm absence of mapping
16+
client := setUpContainer(t, testContainerOptions{
17+
APIPermissions: []string{
18+
PermissionAccessManagement,
19+
},
20+
})
21+
22+
team, err := client.Team.Create(context.Background(), Team{
23+
Name: "TestLdapMappings",
24+
})
25+
require.NoError(t, err)
26+
27+
mappings, err := client.LDAP.GetTeamMappings(context.Background(), team.UUID)
28+
require.NoError(t, err)
29+
require.Empty(t, mappings)
30+
31+
mapping, err := client.LDAP.AddMapping(context.Background(), MappedLdapGroupRequest{
32+
Team: team.UUID,
33+
DistinguishedName: "test.mapping.ldap.dependencytrack",
34+
})
35+
require.NoError(t, err)
36+
require.Equal(t, mapping.DistinguishedName, "test.mapping.ldap.dependencytrack")
37+
require.NotEmpty(t, mapping.UUID)
38+
39+
mappings, err = client.LDAP.GetTeamMappings(context.Background(), team.UUID)
40+
require.NoError(t, err)
41+
require.Equal(t, len(mappings), 1)
42+
require.Equal(t, mappings[0].DistinguishedName, mapping.DistinguishedName)
43+
require.Equal(t, mappings[0].UUID, mapping.UUID)
44+
45+
err = client.LDAP.RemoveMapping(context.Background(), mapping.UUID)
46+
require.NoError(t, err)
47+
48+
mappings, err = client.LDAP.GetTeamMappings(context.Background(), team.UUID)
49+
require.NoError(t, err)
50+
require.Empty(t, mappings)
51+
}
52+
53+
func TestLdapUsers(t *testing.T) {
54+
// 1. Confirm absence of users
55+
// 2. Create user
56+
// 3. Confirm presence of user
57+
// 4. Delete user
58+
// 5. Confirm absence of user
59+
client := setUpContainer(t, testContainerOptions{
60+
APIPermissions: []string{
61+
PermissionAccessManagement,
62+
},
63+
})
64+
65+
users, err := client.LDAP.GetUsers(context.Background(), PageOptions{
66+
PageSize: 10,
67+
})
68+
require.NoError(t, err)
69+
require.Equal(t, users.TotalCount, 0)
70+
require.Empty(t, users.Items)
71+
72+
user, err := client.LDAP.CreateUser(context.Background(), LdapUser{
73+
Username: "TestLdapUsers",
74+
DistinguishedName: "test.user.ldap.dependencytrack",
75+
Email: "test@localhost",
76+
})
77+
require.NoError(t, err)
78+
require.Equal(t, user.Username, "TestLdapUsers")
79+
require.Equal(t, user.DistinguishedName, "Syncing...")
80+
require.Empty(t, user.Email)
81+
require.Empty(t, user.Permissions)
82+
require.Empty(t, user.Teams)
83+
84+
users, err = client.LDAP.GetUsers(context.Background(), PageOptions{
85+
PageSize: 10,
86+
})
87+
require.NoError(t, err)
88+
require.Equal(t, users.TotalCount, 1)
89+
require.Equal(t, len(users.Items), 1)
90+
require.Equal(t, users.Items[0].DistinguishedName, user.DistinguishedName)
91+
require.Equal(t, users.Items[0].Email, user.Email)
92+
require.Equal(t, users.Items[0].Username, user.Username)
93+
94+
err = client.LDAP.DeleteUser(context.Background(), user)
95+
require.NoError(t, err)
96+
97+
users, err = client.LDAP.GetUsers(context.Background(), PageOptions{
98+
PageSize: 10,
99+
})
100+
require.NoError(t, err)
101+
require.Equal(t, users.TotalCount, 0)
102+
require.Empty(t, users.Items)
103+
}

0 commit comments

Comments
 (0)