package testclient import ( "crypto/tls" "time" "gopkg.in/ldap.v2" ) // Fake is a mock client for an LDAP server // The following methods define safe defaults for the return values. In order to adapt this test client // for a specific test, anonymously include it and override the method being tested. In the over-riden // method, if you are not covering all method calls with your override, defer to the parent for handling. type Fake struct { SimpleBindResponse *ldap.SimpleBindResult PasswordModifyResponse *ldap.PasswordModifyResult SearchResponse *ldap.SearchResult } var _ ldap.Client = &Fake{} // NewTestClient returns a new test client with safe default return values func New() *Fake { return &Fake{ SimpleBindResponse: &ldap.SimpleBindResult{ Controls: []ldap.Control{}, }, PasswordModifyResponse: &ldap.PasswordModifyResult{ GeneratedPassword: "", }, SearchResponse: &ldap.SearchResult{ Entries: []*ldap.Entry{}, Referrals: []string{}, Controls: []ldap.Control{}, }, } } // Start starts the LDAP connection func (c *Fake) Start() { return } // StartTLS begins a TLS-wrapped LDAP connection func (c *Fake) StartTLS(config *tls.Config) error { return nil } // Close closes an LDAP connection func (c *Fake) Close() { return } // Bind binds to the LDAP server with a bind DN and password func (c *Fake) Bind(username, password string) error { return nil } // SimpleBind binds to the LDAP server using the Simple Bind mechanism func (c *Fake) SimpleBind(simpleBindRequest *ldap.SimpleBindRequest) (*ldap.SimpleBindResult, error) { return c.SimpleBindResponse, nil } // Add forwards an addition request to the LDAP server func (c *Fake) Add(addRequest *ldap.AddRequest) error { return nil } // Del forwards a deletion request to the LDAP server func (c *Fake) Del(delRequest *ldap.DelRequest) error { return nil } // Modify forwards a modification request to the LDAP server func (c *Fake) Modify(modifyRequest *ldap.ModifyRequest) error { return nil } // Compare ... ? func (c *Fake) Compare(dn, attribute, value string) (bool, error) { return false, nil } // PasswordModify forwards a password modify request to the LDAP server func (c *Fake) PasswordModify(passwordModifyRequest *ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error) { return c.PasswordModifyResponse, nil } // Search forwards a search request to the LDAP server func (c *Fake) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) { return c.SearchResponse, nil } // SearchWithPaging forwards a search request to the LDAP server and pages the response func (c *Fake) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) { return c.SearchResponse, nil } // SetTimeout sets a timeout on the client func (c *Fake) SetTimeout(d time.Duration) { } // NewMatchingSearchErrorClient returns a new MatchingSearchError client sitting on top of the parent // client. This client returns the given error when a search base DN matches the given base DN, and // defers to the parent otherwise. func NewMatchingSearchErrorClient(parent ldap.Client, baseDN string, returnErr error) ldap.Client { return &MatchingSearchErrClient{ Client: parent, BaseDN: baseDN, ReturnErr: returnErr, } } // MatchingSearchErrClient returns the ReturnErr on every Search() where the search base DN matches the given DN // or defers the search to the parent client type MatchingSearchErrClient struct { ldap.Client BaseDN string ReturnErr error } func (c *MatchingSearchErrClient) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) { if searchRequest.BaseDN == c.BaseDN { return nil, c.ReturnErr } return c.Client.Search(searchRequest) } // NewDNMappingClient returns a new DNMappingClient sitting on top of the parent client. This client returns the // ldap entries mapped to with this DN in its' internal DN map, or defers to the parent if the DN is not mapped. func NewDNMappingClient(parent ldap.Client, DNMapping map[string][]*ldap.Entry) ldap.Client { return &DNMappingClient{ Client: parent, DNMapping: DNMapping, } } // DNMappingClient returns the LDAP entry mapped to by the base dn given, or if no mapping happens, defers to the parent type DNMappingClient struct { ldap.Client DNMapping map[string][]*ldap.Entry } func (c *DNMappingClient) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) { if entries, exists := c.DNMapping[searchRequest.BaseDN]; exists { return &ldap.SearchResult{Entries: entries}, nil } return c.Client.Search(searchRequest) } // NewPagingOnlyClient returns a new PagingOnlyClient sitting on top of the parent client. This client returns the // provided search response for any calls to SearchWithPaging, or defers to the parent if the call is not to the // paged search function. func NewPagingOnlyClient(parent ldap.Client, response *ldap.SearchResult) ldap.Client { return &PagingOnlyClient{ Client: parent, Response: response, } } // PagingOnlyClient responds with a canned search result for any calls to SearchWithPaging type PagingOnlyClient struct { ldap.Client Response *ldap.SearchResult } func (c *PagingOnlyClient) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) { return c.Response, nil }