Skip to content

Commit

Permalink
Merge pull request #2977 from rhafer/ldapretry
Browse files Browse the repository at this point in the history
graph: Fix LDAP retry handling
  • Loading branch information
butonic authored Jan 18, 2022
2 parents 4815553 + d57d40a commit c680326
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 36 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/fix-ldapretry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Fix retry handling for LDAP connections

We've fixed the handling of network issues (e.g. connection loss) during LDAP Write Operations
to correcty retry the request.

https://github.com/owncloud/ocis/issues/2974
131 changes: 95 additions & 36 deletions graph/pkg/identity/ldap/reconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,101 @@ func (c ConnWithReconnect) Search(sr *ldap.SearchRequest) (*ldap.SearchResult, e
return nil, ldap.NewError(ldap.ErrorNetwork, errors.New("max retries"))
}

func (c ConnWithReconnect) Add(a *ldap.AddRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}
for try := 0; try <= c.retries; try++ {
err = conn.Add(a)
if !ldap.IsErrorWithCode(err, ldap.ErrorNetwork) {
// non network error, return it to the client
return err
}

c.logger.Debug().Msgf("Network Error. attempt %d", try)
conn, err = c.reconnect(conn)
if err != nil {
return err
}
c.logger.Debug().Msg("retrying LDAP Add")
}
// if we get here we reached the maximum retries. So return an error
return ldap.NewError(ldap.ErrorNetwork, errors.New("max retries"))
}

func (c ConnWithReconnect) Del(d *ldap.DelRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

for try := 0; try <= c.retries; try++ {
err = conn.Del(d)
if !ldap.IsErrorWithCode(err, ldap.ErrorNetwork) {
// non network error, return it to the client
return err
}

c.logger.Debug().Msgf("Network Error. attempt %d", try)
conn, err = c.reconnect(conn)
if err != nil {
return err
}
c.logger.Debug().Msg("retrying LDAP Del")
}
// if we get here we reached the maximum retries. So return an error
return ldap.NewError(ldap.ErrorNetwork, errors.New("max retries"))
}

func (c ConnWithReconnect) Modify(m *ldap.ModifyRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

for try := 0; try <= c.retries; try++ {
err = conn.Modify(m)
if !ldap.IsErrorWithCode(err, ldap.ErrorNetwork) {
// non network error, return it to the client
return err
}

c.logger.Debug().Msgf("Network Error. attempt %d", try)
conn, err = c.reconnect(conn)
if err != nil {
return err
}
c.logger.Debug().Msg("retrying LDAP Modify")
}
// if we get here we reached the maximum retries. So return an error
return ldap.NewError(ldap.ErrorNetwork, errors.New("max retries"))
}

func (c ConnWithReconnect) ModifyDN(m *ldap.ModifyDNRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

for try := 0; try <= c.retries; try++ {
err = conn.ModifyDN(m)
if !ldap.IsErrorWithCode(err, ldap.ErrorNetwork) {
// non network error, return it to the client
return err
}

c.logger.Debug().Msgf("Network Error. attempt %d", try)
conn, err = c.reconnect(conn)
if err != nil {
return err
}
c.logger.Debug().Msg("retrying LDAP ModifyDN")
}
// if we get here we reached the maximum retries. So return an error
return ldap.NewError(ldap.ErrorNetwork, errors.New("max retries"))
}

func (c ConnWithReconnect) GetConnection() (*ldap.Conn, error) {
conn := <-c.conn
if conn.Conn != nil && !ldap.IsErrorWithCode(conn.Error, ldap.ErrorNetwork) {
Expand Down Expand Up @@ -162,42 +257,6 @@ func (c ConnWithReconnect) ExternalBind() error {
return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
}

func (c ConnWithReconnect) Add(a *ldap.AddRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

return conn.Add(a)
}

func (c ConnWithReconnect) Del(d *ldap.DelRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

return conn.Del(d)
}

func (c ConnWithReconnect) Modify(m *ldap.ModifyRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

return conn.Modify(m)
}

func (c ConnWithReconnect) ModifyDN(m *ldap.ModifyDNRequest) error {
conn, err := c.GetConnection()
if err != nil {
return err
}

return conn.ModifyDN(m)
}

func (c ConnWithReconnect) ModifyWithResult(m *ldap.ModifyRequest) (*ldap.ModifyResult, error) {
conn, err := c.GetConnection()
if err != nil {
Expand Down

0 comments on commit c680326

Please sign in to comment.