func TestExtractMembers(t *testing.T) { var testCases = []struct { name string client ldap.Client expectedError error expectedMembers []*ldap.Entry }{ { name: "group lookup errors", client: testclient.NewMatchingSearchErrorClient( testclient.New(), "cn=testGroup,ou=groups,dc=example,dc=com", errors.New("generic search error"), ), expectedError: errors.New("generic search error"), expectedMembers: nil, }, { name: "member lookup errors", // this is a nested test client, the first nest tries to error on the user DN // the second nest attempts to give back from the DN mapping // the third nest is the default "safe" impl from ldaputil client: testclient.NewMatchingSearchErrorClient( testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "cn=testGroup,ou=groups,dc=example,dc=com": {newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com")}, }, ), "cn=testUser,ou=users,dc=example,dc=com", errors.New("generic search error"), ), expectedError: interfaces.NewMemberLookupError("cn=testGroup,ou=groups,dc=example,dc=com", "cn=testUser,ou=users,dc=example,dc=com", errors.New("generic search error")), expectedMembers: nil, }, { name: "no errors", client: testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "cn=testGroup,ou=groups,dc=example,dc=com": {newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com")}, "cn=testUser,ou=users,dc=example,dc=com": {newTestUser("testUser")}, }, ), expectedError: nil, expectedMembers: []*ldap.Entry{newTestUser("testUser")}, }, } for _, testCase := range testCases { ldapInterface := newTestLDAPInterface(testCase.client) members, err := ldapInterface.ExtractMembers("cn=testGroup,ou=groups,dc=example,dc=com") if !reflect.DeepEqual(err, testCase.expectedError) { t.Errorf("%s: incorrect error returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedError, err) } if !reflect.DeepEqual(members, testCase.expectedMembers) { t.Errorf("%s: incorrect members returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedMembers, members) } } }
func TestListGroups(t *testing.T) { var testCases = []struct { name string client ldap.Client groupUIDAttribute string expectedError error expectedGroups []string }{ { name: "query errors", client: testclient.NewMatchingSearchErrorClient( testclient.New(), "ou=groups,dc=example,dc=com", errors.New("generic search error"), ), expectedError: errors.New("generic search error"), expectedGroups: nil, }, { name: "no UID on entry", client: testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "ou=groups,dc=example,dc=com": {newTestGroup("", "cn=testUser,ou=users,dc=example,dc=com")}, }, ), groupUIDAttribute: "cn", expectedError: fmt.Errorf("unable to find LDAP group UID for %s", newTestGroup("", "cn=testUser,ou=users,dc=example,dc=com")), expectedGroups: nil, }, { name: "no error", client: testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "ou=groups,dc=example,dc=com": {newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com")}, }, ), expectedError: nil, expectedGroups: []string{"cn=testGroup,ou=groups,dc=example,dc=com"}, }, } for _, testCase := range testCases { ldapInterface := newTestLDAPInterface(testCase.client) if len(testCase.groupUIDAttribute) > 0 { ldapInterface.groupQuery.QueryAttribute = testCase.groupUIDAttribute } groupNames, err := ldapInterface.ListGroups() if !reflect.DeepEqual(err, testCase.expectedError) { t.Errorf("%s: incorrect error returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedError, err) } if !reflect.DeepEqual(groupNames, testCase.expectedGroups) { t.Errorf("%s: incorrect entry returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedGroups, groupNames) } } }
func TestGroupEntryFor(t *testing.T) { var testCases = []struct { name string cacheSeed map[string]*ldap.Entry queryBaseDNOverride string client ldap.Client expectedError error expectedEntry *ldap.Entry }{ { name: "cached get", cacheSeed: map[string]*ldap.Entry{"cn=testGroup,ou=groups,dc=example,dc=com": newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com")}, expectedError: nil, expectedEntry: newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com"), }, { name: "search request failure", queryBaseDNOverride: "dc=foo", expectedError: ldaputil.NewQueryOutOfBoundsError("cn=testGroup,ou=groups,dc=example,dc=com", "dc=foo"), expectedEntry: nil, }, { name: "query failure", client: testclient.NewMatchingSearchErrorClient( testclient.New(), "cn=testGroup,ou=groups,dc=example,dc=com", errors.New("generic search error"), ), expectedError: errors.New("generic search error"), expectedEntry: nil, }, { name: "no errors", client: testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "cn=testGroup,ou=groups,dc=example,dc=com": {newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com")}, }, ), expectedError: nil, expectedEntry: newTestGroup("testGroup", "cn=testUser,ou=users,dc=example,dc=com"), }, } for _, testCase := range testCases { ldapInterface := newTestLDAPInterface(testCase.client) if len(testCase.cacheSeed) > 0 { ldapInterface.cachedGroups = testCase.cacheSeed } if len(testCase.queryBaseDNOverride) > 0 { ldapInterface.groupQuery.BaseDN = testCase.queryBaseDNOverride } entry, err := ldapInterface.GroupEntryFor("cn=testGroup,ou=groups,dc=example,dc=com") if !reflect.DeepEqual(err, testCase.expectedError) { t.Errorf("%s: incorrect error returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedError, err) } if !reflect.DeepEqual(entry, testCase.expectedEntry) { t.Errorf("%s: incorrect entry returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedEntry, entry) } } }
// TestPopulateCacheAfterExtractMembers ensures that the cache is only listed as fully populated after a // populateCache call and not after a partial fill from an ExtractMembers call func TestPopulateCacheAfterExtractMembers(t *testing.T) { client := testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "ou=users,dc=example,dc=com": {newTestUser("testUser", "testGroup")}, }, ) ldapInterface := newTestADLDAPInterface(client) _, err := ldapInterface.ExtractMembers("testGroup") if err != nil { t.Errorf("unexpected error: %v", err) } // both queries use the same BaseDN so we change what the client returns to simulate not applying the group-specific filter client.(*testclient.DNMappingClient).DNMapping["ou=users,dc=example,dc=com"] = []*ldap.Entry{ newTestUser("testUser", "testGroup"), newTestUser("testUser2", "testGroup2")} expectedCache := map[string][]*ldap.Entry{ "testGroup": {newTestUser("testUser", "testGroup")}, "testGroup2": {newTestUser("testUser2", "testGroup2")}, } err = ldapInterface.populateCache() if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(expectedCache, ldapInterface.ldapGroupToLDAPMembers) { t.Errorf("incorrect cache state:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", expectedCache, ldapInterface.ldapGroupToLDAPMembers) } }
func TestPopulateCache(t *testing.T) { var testCases = []struct { name string cacheSeed map[string][]*ldap.Entry searchDNOverride string client ldap.Client expectedError error expectedCache map[string][]*ldap.Entry }{ { name: "cache already populated", cacheSeed: map[string][]*ldap.Entry{ "testGroup": {newTestUser("testUser", "testGroup")}, }, expectedError: nil, expectedCache: map[string][]*ldap.Entry{ "testGroup": {newTestUser("testUser", "testGroup")}, }, }, { name: "user query error", client: testclient.NewMatchingSearchErrorClient( testclient.New(), "ou=users,dc=example,dc=com", errors.New("generic search error"), ), expectedError: errors.New("generic search error"), expectedCache: make(map[string][]*ldap.Entry), // won't be nil but will be empty }, { name: "cache populated correctly", client: testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "ou=users,dc=example,dc=com": {newTestUser("testUser", "testGroup")}, }, ), expectedError: nil, expectedCache: map[string][]*ldap.Entry{ "testGroup": {newTestUser("testUser", "testGroup")}, }, }, } for _, testCase := range testCases { ldapInterface := newTestADLDAPInterface(testCase.client) if len(testCase.cacheSeed) > 0 { ldapInterface.ldapGroupToLDAPMembers = testCase.cacheSeed ldapInterface.cacheFullyPopulated = true } err := ldapInterface.populateCache() if !reflect.DeepEqual(err, testCase.expectedError) { t.Errorf("%s: incorrect error returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedError, err) } if !reflect.DeepEqual(testCase.expectedCache, ldapInterface.ldapGroupToLDAPMembers) { t.Errorf("%s: incorrect cache state:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedCache, ldapInterface.ldapGroupToLDAPMembers) } } }
func TestExtractMembers(t *testing.T) { // we don't have a test case for an error on a bad search request as search request errors can only occur if // the search attribute is the DN, and we do not allow DN to be a group UID for this schema var testCases = []struct { name string cacheSeed map[string][]*ldap.Entry client ldap.Client expectedError error expectedMembers []*ldap.Entry }{ { name: "members cached", cacheSeed: map[string][]*ldap.Entry{ "testGroup": {newTestUser("testUser", "testGroup")}, }, expectedError: nil, expectedMembers: []*ldap.Entry{newTestUser("testUser", "testGroup")}, }, { name: "user query error", client: testclient.NewMatchingSearchErrorClient( testclient.New(), "ou=users,dc=example,dc=com", errors.New("generic search error"), ), expectedError: errors.New("generic search error"), expectedMembers: nil, }, { name: "no errors", client: testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "ou=users,dc=example,dc=com": {newTestUser("testUser", "testGroup")}, }, ), expectedError: nil, expectedMembers: []*ldap.Entry{newTestUser("testUser", "testGroup")}, }, } for _, testCase := range testCases { ldapInterface := newTestADLDAPInterface(testCase.client) if len(testCase.cacheSeed) > 0 { ldapInterface.ldapGroupToLDAPMembers = testCase.cacheSeed } members, err := ldapInterface.ExtractMembers("testGroup") if !reflect.DeepEqual(err, testCase.expectedError) { t.Errorf("%s: incorrect error returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedError, err) } if !reflect.DeepEqual(members, testCase.expectedMembers) { t.Errorf("%s: incorrect members returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", testCase.name, testCase.expectedMembers, members) } } }
func TestListGroups(t *testing.T) { client := testclient.NewDNMappingClient( testclient.New(), map[string][]*ldap.Entry{ "ou=users,dc=example,dc=com": {newTestUser("testUser", "testGroup")}, }, ) ldapInterface := newTestADLDAPInterface(client) groups, err := ldapInterface.ListGroups() if !reflect.DeepEqual(err, nil) { t.Errorf("listing groups: incorrect error returned:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", nil, err) } if !reflect.DeepEqual(groups, []string{"testGroup"}) { t.Errorf("listing groups: incorrect group list:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", []string{"testGroup"}, groups) } }