Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quality improvements in: testdirectory and packets #24

Merged
merged 6 commits into from Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions entry_test.go
Expand Up @@ -76,7 +76,8 @@ func TestEntry_PrettyPrint(t *testing.T) {
entry: &Entry{
DN: "uid=alice",
Attributes: []*EntryAttribute{
NewEntryAttribute("cn", []string{"alice"})},
NewEntryAttribute("cn", []string{"alice"}),
},
},
writer: new(strings.Builder),
want: " DN: uid=alice\n cn: [alice]\n",
Expand All @@ -86,7 +87,8 @@ func TestEntry_PrettyPrint(t *testing.T) {
entry: &Entry{
DN: "uid=alice",
Attributes: []*EntryAttribute{
NewEntryAttribute("cn", []string{"alice"})},
NewEntryAttribute("cn", []string{"alice"}),
},
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion packet.go
Expand Up @@ -461,7 +461,7 @@ func (p *packet) searchParmeters() (*searchParameters, error) {
}
searchFor.attributes = make([]string, 0, len(attributesPacket.Children))
for idx, attribute := range attributesPacket.Children {
if err := attributesPacket.assert(ber.ClassUniversal, ber.TypeConstructed, withTag(ber.TagOctetString), withAssertChild(idx)); err != nil {
if err := attributesPacket.assert(ber.ClassUniversal, ber.TypePrimitive, withTag(ber.TagOctetString), withAssertChild(idx)); err != nil {
return nil, fmt.Errorf("%s: invalid attribute child packet: %w", op, err)
}
searchFor.attributes = append(searchFor.attributes, attribute.Data.String())
Expand Down
4 changes: 2 additions & 2 deletions testdirectory/directory.go
Expand Up @@ -673,8 +673,8 @@ func (d *Directory) ClientKey() string {
}

// Controls returns all the current bind controls for the Directory
func (d *Directory) Controls() []*gldap.Entry {
return d.users
func (d *Directory) Controls() []gldap.Control {
return d.controls
}

// SetControls sets the bind controls.
Expand Down
153 changes: 129 additions & 24 deletions testdirectory/directory_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"strings"
"testing"

"github.com/go-ldap/ldap/v3"
Expand Down Expand Up @@ -76,6 +77,18 @@ func Test_Start(t *testing.T) {

err := c.Bind(userDN, testPwd)
require.NoError(err)

clientCert, err := tls.X509KeyPair([]byte(td.ClientCert()), []byte(td.ClientKey()))
require.NoError(err)
certpool := x509.NewCertPool()
certpool.AppendCertsFromPEM([]byte(td.Cert()))
tlsConfig := &tls.Config{
RootCAs: certpool,
Certificates: []tls.Certificate{clientCert},
}
conn, err := ldap.DialURL(fmt.Sprintf("ldaps://localhost:%d", td.Port()), ldap.DialWithTLSConfig(tlsConfig))
require.NoError(err)
conn.Close()
})
t.Run("start-tls", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
Expand Down Expand Up @@ -104,6 +117,26 @@ func Test_Start(t *testing.T) {
err = c.Bind(userDN, testPwd)
require.NoError(err)
})
t.Run("start-with-TestingT", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
buf := &strings.Builder{}
bufLogger := hclog.New(&hclog.LoggerOptions{
Name: "my-app",
Level: hclog.LevelFromString("DEBUG"),
Output: buf,
})
l, err := testdirectory.NewLogger(bufLogger)
require.NoError(err)
assert.NotNil(l)

td := testdirectory.Start(l, testdirectory.WithLogger(l, bufLogger))
td.Stop()
assert.Contains(buf.String(), "stopped")
})
t.Run("start-gldap.WithDisablePanicRecovery", func(t *testing.T) {
// not sure there's anything that's assertable here...
_ = testdirectory.Start(t, testdirectory.WithDisablePanicRecovery(t, true))
})
}

func TestDirectory_SimpleBindResponse(t *testing.T) {
Expand All @@ -116,6 +149,11 @@ func TestDirectory_SimpleBindResponse(t *testing.T) {
testdirectory.WithLogger(t, testLogger),
testdirectory.WithDefaults(t, &testdirectory.Defaults{AllowAnonymousBind: true}),
)

p, err := gldap.NewControlBeheraPasswordPolicy(gldap.WithGraceAuthNsRemaining(60))
require.NoError(t, err)
td.SetControls(p)

users := testdirectory.NewUsers(t, []string{"alice", "bob"})
td.SetUsers(users...)

Expand Down Expand Up @@ -164,10 +202,10 @@ func TestDirectory_SimpleBindResponse(t *testing.T) {
}
}

func TestDirectory_SearchUsersResponse(t *testing.T) {
func TestDirectory_SearchResponse(t *testing.T) {
t.Parallel()
testLogger := hclog.New(&hclog.LoggerOptions{
Name: "TestDirectory_SearchUsersResponse-logger",
Name: "TestDirectory_SearchResponse-logger",
Level: hclog.Error,
})

Expand Down Expand Up @@ -204,7 +242,7 @@ func TestDirectory_SearchUsersResponse(t *testing.T) {
name string
filter string
baseDN string
wantEntry *gldap.Entry
wantEntries []*gldap.Entry
wantErr bool
wantErrContains string
}{
Expand All @@ -216,16 +254,22 @@ func TestDirectory_SearchUsersResponse(t *testing.T) {
wantErrContains: `LDAP Result Code 32 "No Such Object"`,
},
{
name: "alice-found",
filter: fmt.Sprintf("(%s=alice,%s)", testdirectory.DefaultUserAttr, testdirectory.DefaultUserDN),
baseDN: testdirectory.DefaultUserDN,
wantEntry: users[0],
name: "alice-found",
filter: fmt.Sprintf("(%s=alice,%s)", testdirectory.DefaultUserAttr, testdirectory.DefaultUserDN),
baseDN: testdirectory.DefaultUserDN,
wantEntries: []*gldap.Entry{users[0]},
},
{
name: "admin-group-found",
filter: fmt.Sprintf("(%s=admin,%s)", testdirectory.DefaultGroupAttr, testdirectory.DefaultGroupDN),
baseDN: testdirectory.DefaultGroupDN,
wantEntry: groups[0],
name: "admin-group-found",
filter: fmt.Sprintf("(%s=admin,%s)", testdirectory.DefaultGroupAttr, testdirectory.DefaultGroupDN),
baseDN: testdirectory.DefaultGroupDN,
wantEntries: []*gldap.Entry{groups[0]},
},
{
name: "token-group-found",
filter: fmt.Sprintf("(%s=admin,%s)", testdirectory.DefaultGroupAttr, testdirectory.DefaultGroupDN),
baseDN: "<SID=S-1-1>",
wantEntries: []*gldap.Entry{groups[0]},
},
{
name: "group-not-found",
Expand All @@ -235,10 +279,10 @@ func TestDirectory_SearchUsersResponse(t *testing.T) {
wantErrContains: `LDAP Result Code 32 "No Such Object"`,
},
{
name: "admin-member-found",
filter: fmt.Sprintf("(%s=alice,%s)", testdirectory.DefaultUserAttr, testdirectory.DefaultUserDN),
baseDN: testdirectory.DefaultGroupDN,
wantEntry: groups[0],
name: "admin-member-found",
filter: fmt.Sprintf("(%s=alice,%s)", testdirectory.DefaultUserAttr, testdirectory.DefaultUserDN),
baseDN: testdirectory.DefaultGroupDN,
wantEntries: []*gldap.Entry{groups[0]},
},
{
name: "admin-member-not-found",
Expand All @@ -248,10 +292,10 @@ func TestDirectory_SearchUsersResponse(t *testing.T) {
wantErrContains: `LDAP Result Code 32 "No Such Object"`,
},
{
name: "admin-member-found-upn",
filter: fmt.Sprintf("(userPrincipalName=eve@%s,%s)", "example.com", testdirectory.DefaultUserDN),
baseDN: testdirectory.DefaultGroupDN,
wantEntry: groups[1],
name: "admin-member-found-upn",
filter: fmt.Sprintf("(userPrincipalName=eve@%s,%s)", "example.com", testdirectory.DefaultUserDN),
baseDN: testdirectory.DefaultGroupDN,
wantEntries: []*gldap.Entry{groups[1]},
},
}

Expand All @@ -260,9 +304,10 @@ func TestDirectory_SearchUsersResponse(t *testing.T) {
assert, require := assert.New(t), require.New(t)
client := td.Conn()
defer func() { client.Close() }()
_, err := client.Search(&ldap.SearchRequest{
BaseDN: tc.baseDN,
Filter: tc.filter,
results, err := client.Search(&ldap.SearchRequest{
BaseDN: tc.baseDN,
Filter: tc.filter,
Attributes: []string{"name", "email", "password"},
})
if tc.wantErr {
require.Error(err)
Expand All @@ -272,6 +317,16 @@ func TestDirectory_SearchUsersResponse(t *testing.T) {
return
}
assert.NoError(err)
found := []*gldap.Entry{}
for _, e := range results.Entries {
attrs := map[string][]string{}
for _, a := range e.Attributes {
attrs[a.Name] = a.Values
}
entry := gldap.NewEntry(e.DN, attrs)
found = append(found, entry)
}
assert.Equal(tc.wantEntries, found)
})
}
}
Expand Down Expand Up @@ -503,8 +558,9 @@ func TestDirectory_AddResponse(t *testing.T) {
}
require.NoError(err)
result, err := client.Search(&ldap.SearchRequest{
BaseDN: tc.dn,
Filter: fmt.Sprintf("(%s)", tc.dn),
BaseDN: tc.dn,
Filter: fmt.Sprintf("(%s)", tc.dn),
Attributes: []string{"name", "email", "password"},
})
require.NoError(err)
assert.Equal(len(tc.wantEntry.Attributes), len(result.Entries[0].Attributes))
Expand All @@ -515,3 +571,52 @@ func TestDirectory_AddResponse(t *testing.T) {
})
}
}

func TestGetters(t *testing.T) {
t.Parallel()
assert, require := assert.New(t), require.New(t)

testLogger := hclog.New(&hclog.LoggerOptions{
Name: "TestDirectory_AddResponse-logger",
Level: hclog.Error,
})
td := testdirectory.Start(t,
testdirectory.WithLogger(t, testLogger),
)
groups := []*gldap.Entry{
testdirectory.NewGroup(t, "admin", []string{"alice"}),
testdirectory.NewGroup(t, "admin-upn", []string{"eve"}, testdirectory.WithDefaults(t, &testdirectory.Defaults{UPNDomain: "example.com"})),
}

tokenGroups := map[string][]*gldap.Entry{
"S-1-1": {
testdirectory.NewGroup(t, "admin", []string{"alice"}),
},
}
sidBytes, err := gldap.SIDBytes(1, 1)
require.NoError(err)

users := testdirectory.NewUsers(t, []string{"alice", "bob"}, testdirectory.WithMembersOf(t, "admin"), testdirectory.WithTokenGroups(t, sidBytes))
users = append(
users,
testdirectory.NewUsers(
t,
[]string{"eve"},
testdirectory.WithDefaults(t, &testdirectory.Defaults{UPNDomain: "example.com"}),
testdirectory.WithMembersOf(t, "admin"))...,
)
ctrl, err := gldap.NewControlBeheraPasswordPolicy(gldap.WithGraceAuthNsRemaining(60))
require.NoError(err)
td.SetControls(ctrl)

td.SetUsers(users...)
td.SetGroups(groups...)
td.SetTokenGroups(tokenGroups)
td.SetAllowAnonymousBind(true)

assert.True(td.AllowAnonymousBind())
assert.Equal(groups, td.Groups())
assert.Equal(tokenGroups, td.TokenGroups())
assert.Equal(users, td.Users())
assert.Equal([]gldap.Control{ctrl}, td.Controls())
}
78 changes: 78 additions & 0 deletions testdirectory/options_test.go
@@ -0,0 +1,78 @@
package testdirectory

import (
"testing"

"github.com/hashicorp/go-hclog"
"github.com/jimlambrt/gldap"
"github.com/stretchr/testify/assert"
)

func TestAllOptions(t *testing.T) {
testLogger := hclog.New(&hclog.LoggerOptions{
Name: "my-app",
Level: hclog.LevelFromString("DEBUG"),
})
t.Run("WithDefaults", func(t *testing.T) {
assert := assert.New(t)
opts := getOpts(t,
WithLogger(t, testLogger),
WithDefaults(t, &Defaults{
UserAttr: "user-attr",
GroupAttr: "grp-attr",
Users: NewUsers(t, []string{"alice"}),
Groups: []*gldap.Entry{NewGroup(t, "admin", []string{"alice"})},
UserDN: "user-dn",
GroupDN: "grp-dn",
TokenGroups: map[string][]*gldap.Entry{
"S-1-1": {
NewGroup(t, "admin", []string{"alice"}),
},
},
AllowAnonymousBind: true,
UPNDomain: "domain",
}))
testOpts := defaults(t)
testOpts.withLogger = testLogger
testOpts.withDefaults.UserAttr = "user-attr"
testOpts.withDefaults.GroupAttr = "grp-attr"
testOpts.withDefaults.UserDN = "user-dn"
testOpts.withDefaults.GroupDN = "grp-dn"
testOpts.withDefaults.Users = NewUsers(t, []string{"alice"})
testOpts.withDefaults.Groups = []*gldap.Entry{NewGroup(t, "admin", []string{"alice"})}
testOpts.withDefaults.TokenGroups = map[string][]*gldap.Entry{
"S-1-1": {
NewGroup(t, "admin", []string{"alice"}),
},
}
testOpts.withDefaults.AllowAnonymousBind = true
testOpts.withDefaults.UPNDomain = "domain"
assert.Equal(opts, testOpts)
})
t.Run("withFirst", func(t *testing.T) {
assert := assert.New(t)
opts := getOpts(t, WithLogger(t, testLogger), withFirst(t))
testOpts := defaults(t)
testOpts.withLogger = testLogger
testOpts.withFirst = true
assert.Equal(opts, testOpts)
})
t.Run("WithDisablePanicRecovery", func(t *testing.T) {
assert := assert.New(t)
opts := getOpts(t, WithLogger(t, testLogger), WithDisablePanicRecovery(t, true))
testOpts := defaults(t)
testOpts.withLogger = testLogger
testOpts.withDisablePanicRecovery = true
assert.Equal(opts, testOpts)
})
}

func Test_applyOpts(t *testing.T) {
assert := assert.New(t)
opts := options{}
applyOpts(&opts, nil)
assert.Equal(options{}, opts)

applyOpts(&opts, withFirst(t))
assert.Equal(options{withFirst: true}, opts)
}
24 changes: 24 additions & 0 deletions testdirectory/testing_test.go
@@ -0,0 +1,24 @@
package testdirectory_test

import (
"testing"

"github.com/jimlambrt/gldap/testdirectory"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewMemberOf(t *testing.T) {
t.Run("simple", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
DNs := testdirectory.NewMemberOf(t,
[]string{"grp1", "grp2"},
testdirectory.WithDefaults(t, &testdirectory.Defaults{
GroupDN: "grp-dn",
GroupAttr: "grp-attr",
}))
require.Len(DNs, 2)
assert.Equal("grp-attr=grp1,grp-dn", DNs[0])
assert.Equal("grp-attr=grp2,grp-dn", DNs[1])
})
}