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) } } }
// TestErrNoSuchObject tests that our LDAP search correctly wraps the LDAP server error func TestErrNoSuchObject(t *testing.T) { var testCases = []struct { name string searchRequest *ldap.SearchRequest expectedError error }{ { name: "valid search", searchRequest: &ldap.SearchRequest{ BaseDN: "uid=john,o=users,dc=example,dc=com", }, expectedError: nil, }, { name: "invalid search", searchRequest: &ldap.SearchRequest{ BaseDN: "ou=groups,dc=example,dc=com", }, expectedError: &errNoSuchObject{baseDN: "ou=groups,dc=example,dc=com"}, }, } for _, testCase := range testCases { testClient := testclient.NewMatchingSearchErrorClient(testclient.New(), "ou=groups,dc=example,dc=com", ldap.NewError(ldap.LDAPResultNoSuchObject, errors.New("")), ) testConfig := testclient.NewConfig(testClient) if _, err := QueryForEntries(testConfig, testCase.searchRequest); !reflect.DeepEqual(err, testCase.expectedError) { t.Errorf("%s: error did not match:\n\texpected:\n\t%v\n\tgot:\n\t%v", testCase.name, testCase.expectedError, err) } } }
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) } } }
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 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 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) } } }