Skip to content

Commit

Permalink
add tests to groups
Browse files Browse the repository at this point in the history
  • Loading branch information
pquerna committed Oct 15, 2024
1 parent 858d700 commit b1d07a3
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 7 deletions.
12 changes: 6 additions & 6 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3'
services:
openldap:
image: osixia/openldap:latest
Expand All @@ -8,10 +8,10 @@ services:
- "389:389"
- "636:636"
# Uncomment these lines if you want to persist data.
# volumes:
# - ./data/certificates:/container/service/slapd/assets/certs
# - ./data/slapd/database:/var/lib/ldap
# - ./data/slapd/config:/etc/ldap/slapd.d
volumes:
- ./data/certificates:/container/service/slapd/assets/certs
- ./data/slapd/database:/var/lib/ldap
- ./data/slapd/config:/etc/ldap/slapd.d
environment:
# If you want to persist data, set the UID/GID to the owner user/groups in your volume mounts
# - LDAP_OPENLDAP_UID=501
Expand Down Expand Up @@ -39,7 +39,7 @@ services:
container_name: phpldapadmin
hostname: phpldapadmin
ports:
- "80:80"
- "8080:80"
environment:
- PHPLDAPADMIN_LDAP_HOSTS=openldap
- PHPLDAPADMIN_HTTPS=false
Expand Down
104 changes: 104 additions & 0 deletions pkg/connector/connector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package connector

import (
"context"
"os"
"path/filepath"

"embed"
"net/url"
"testing"

"github.com/conductorone/baton-ldap/pkg/config"
"github.com/go-ldap/ldap/v3"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/openldap"

_ "embed"
)

//go:embed testfixtures/*.ldif
var fixtures embed.FS

func TestValidate(t *testing.T) {
ctx, done := context.WithCancel(context.Background())
defer done()

connector, err := createConnector(ctx, t, "")
require.NoError(t, err)

_, err = connector.Validate(ctx)
require.NoError(t, err)
}

func createConnector(ctx context.Context, t *testing.T, fixtureName string) (*LDAP, error) {
opts := []testcontainers.ContainerCustomizer{
openldap.WithAdminUsername("admin"),
openldap.WithAdminPassword("hunter2"),
}

if fixtureName != "" {
data, err := fixtures.ReadFile(filepath.Join("testfixtures", fixtureName))
if err != nil {
return nil, err
}
fd, err := os.CreateTemp("", "ldif")
if err != nil {
return nil, err
}
fdPath := fd.Name()
fd.Close()

Check failure on line 51 in pkg/connector/connector_test.go

View workflow job for this annotation

GitHub Actions / go-lint

unhandled-error: Unhandled error in call to function os.File.Close (revive)
t.Cleanup(func() {
os.Remove(fdPath)

Check failure on line 53 in pkg/connector/connector_test.go

View workflow job for this annotation

GitHub Actions / go-lint

unhandled-error: Unhandled error in call to function os.Remove (revive)
})

err = os.WriteFile(fdPath, data, 0600)
if err != nil {
return nil, err
}
opts = append(opts, openldap.WithInitialLdif(fdPath))
}

container, err := openldap.Run(ctx,
"bitnami/openldap:2.6.6",
opts...,
)
if err != nil {
return nil, err
}
t.Cleanup(func() {
require.NoError(t, container.Terminate(context.Background()))
})

serverURL, err := container.ConnectionString(ctx)
if err != nil {
return nil, err
}

sux, err := url.Parse(serverURL)
if err != nil {
return nil, err
}

bindDN, err := ldap.ParseDN("cn=admin,dc=example,dc=org")
if err != nil {
return nil, err
}

cf := &config.Config{
ServerURL: sux,
BindDN: bindDN,
BaseDN: mustParseDN(t, "dc=example,dc=org"),
GroupSearchDN: mustParseDN(t, "ou=groups,dc=example,dc=org"),
UserSearchDN: mustParseDN(t, "ou=users,dc=example,dc=org"),
BindPassword: "hunter2",
}
return New(ctx, cf)
}

func mustParseDN(t *testing.T, input string) *ldap.DN {
dn, err := ldap.ParseDN(input)
require.NoError(t, err)
return dn
}
9 changes: 8 additions & 1 deletion pkg/connector/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package connector

import (
"context"
"errors"
"fmt"

"github.com/conductorone/baton-ldap/pkg/ldap"
Expand Down Expand Up @@ -92,7 +93,7 @@ func (g *groupResourceType) List(ctx context.Context, _ *v2.ResourceId, pt *pagi
ResourcesPageSize,
)
if err != nil {
return nil, "", nil, fmt.Errorf("ldap-connector: failed to list groups: %w", err)
return nil, "", nil, fmt.Errorf("ldap-connector: failed to list groups in '%s': %w", g.groupSearchDN.String(), err)
}

pageToken, err := bag.NextToken(nextPage)
Expand Down Expand Up @@ -358,6 +359,12 @@ func (g *groupResourceType) Revoke(ctx context.Context, grant *v2.Grant) (annota
modifyRequest,
)
if err != nil {
var lerr *ldap3.Error
if errors.As(err, &lerr) {
if lerr.ResultCode == ldap3.LDAPResultNoSuchAttribute {
return nil, nil
}
}
return nil, fmt.Errorf("ldap-connector: failed to revoke group membership from user: %w", err)
}

Expand Down
87 changes: 87 additions & 0 deletions pkg/connector/group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package connector

import (
"context"
"testing"

v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
"github.com/conductorone/baton-sdk/pkg/pagination"
"github.com/stretchr/testify/require"
)

func TestGroupGrantRevoke(t *testing.T) {
ctx, done := context.WithCancel(context.Background())
defer done()

connector, err := createConnector(ctx, t, "simple..ldif")
require.NoError(t, err)

gb := groupBuilder(connector.client, connector.config.GroupSearchDN, connector.config.UserSearchDN)

groups, pt, _, err := gb.List(ctx, nil, &pagination.Token{})
require.NoError(t, err)
require.Len(t, groups, 2)
require.Empty(t, pt)

staffGroup := pluck(groups, func(g *v2.Resource) bool {
return g.GetDisplayName() == "staff"
})
require.NotNil(t, staffGroup)

testGroup := pluck(groups, func(g *v2.Resource) bool {
return g.GetDisplayName() == "test"
})
require.NotNil(t, testGroup)

ents, pt, _, err := gb.Entitlements(ctx, testGroup, &pagination.Token{})
require.NoError(t, err)
require.Empty(t, pt)
require.Len(t, ents, 1)

membershipEnt := ents[0]

grants, pt, _, err := gb.Grants(ctx, testGroup, &pagination.Token{})
require.NoError(t, err)
require.Empty(t, pt)
require.Len(t, grants, 1)

rogerGrant := grants[0]
_, err = gb.Revoke(ctx, rogerGrant)
require.NoError(t, err)
// test double revoke doesn't cause a hard error
_, err = gb.Revoke(ctx, rogerGrant)
require.NoError(t, err)

// verify 0 grants
grants, pt, _, err = gb.Grants(ctx, testGroup, &pagination.Token{})
require.NoError(t, err)
require.Empty(t, pt)
require.Len(t, grants, 0)

_, err = gb.Grant(ctx, rogerGrant.Principal, membershipEnt)
require.NoError(t, err)
// test double revoke doesn't cause a hard error
_, err = gb.Grant(ctx, rogerGrant.Principal, membershipEnt)
require.NoError(t, err)

// verify 1 grant
grants, pt, _, err = gb.Grants(ctx, testGroup, &pagination.Token{})
require.NoError(t, err)
require.Empty(t, pt)
require.Len(t, grants, 1)

// verify its roger!
require.EqualExportedValues(t, rogerGrant.Principal, grants[0].Principal)
require.EqualExportedValues(t, rogerGrant.Entitlement, grants[0].Entitlement)
require.Equal(t, rogerGrant.Id, grants[0].Id)
}

func pluck[T any](slice []T, fn func(v T) bool) T {
var emptyT T
for _, v := range slice {
if fn(v) {
return v
}
}
return emptyT
}
41 changes: 41 additions & 0 deletions pkg/connector/testfixtures/simple..ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# simple ldif file for testing
version: 1

dn: ou=groups,dc=example,dc=org
objectclass: organizationalUnit
objectclass: top
ou: groups

dn: cn=staff,ou=groups,dc=example,dc=org
cn: staff
gidnumber: 500
objectclass: posixGroup
objectclass: top

dn: cn=test,ou=groups,dc=example,dc=org
cn: test
gidnumber: 501
memberUid: roger
objectclass: posixGroup
objectclass: top

# Entry 5: ou=users,dc=example,dc=org
# dn: ou=users,dc=example,dc=org
# objectclass: organizationalUnit
# objectclass: top
# ou: users

# Entry 6: cn=roger,ou=users,dc=example,dc=org
dn: cn=roger,ou=users,dc=example,dc=org
cn: roger
gidnumber: 500
givenname: Roger Rabbit
homedirectory: /home/roger
loginshell: /bin/bash
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: top
sn: Rabbit
uid: roger
uidnumber: 1000
userpassword: {CRYPT}$6$Sy1sX75G$/.nlmUpTeW7REXKsdXjRZVXitOrFPk5uEvGs/eC8cXiD0WHlNBT33DDlHlgkP.eiOM5t6VrF1iDj8kYUMPwkT0

0 comments on commit b1d07a3

Please sign in to comment.