user_ldap icon indicating copy to clipboard operation
user_ldap copied to clipboard

ownCloud shares are removed temporarily when LDAP server is not available

Open agross opened this issue 7 years ago • 20 comments

Today I needed to reboot my LDAP server. The reboot caused the LDAP connection to be broken, but what made matters worse is that shares created by LDAP users are removed for non-LDAP enabled accounts.

Consider this setup:

  1. User A is authenticated against LDAP
  2. User B has a normal ownCloud account
  3. User A shares a directory D to user B
  4. User B syncs using his or her ownCloud client , D is downloaded
  5. The LDAP server is rebooted, hence the connection is lost and A is unable to authenticate
  6. The ownCloud client of user B notifies the user that D has been unshared and deletes D from disk
  7. LDAP server comes back online
  8. Shares are restored
  9. User B needs to redownload D

The problem is that D contains about 20 GB of files, and these 20GB are added to our allotted network bandwidth. Consider you need to reboot LDAP quite often, it always causes those 20GB to be deleted and redownloaded a couple of minutes later.

agross avatar Feb 04 '18 16:02 agross

Expected behavior. share is still mounted but inaccessible with "503 Storage Not Available"

PVince81 avatar Feb 05 '18 15:02 PVince81

@butonic @tomneedham

PVince81 avatar Feb 05 '18 15:02 PVince81

Ok, but does step 6 really need to delete all files from disk? IMHO Storage Not Available does not mean that the share was actually removed.

agross avatar Feb 05 '18 16:02 agross

Internally "Storage Not Available" tells any clients to "leave everything as it is" so no deletion would happen.

PVince81 avatar Feb 06 '18 08:02 PVince81

and with "Storage Not Available" it is meant "Storage Temporarily Not Available, Please Try Again Later"

PVince81 avatar Feb 06 '18 08:02 PVince81

If I understand you correctly this is a client issue?

agross avatar Feb 06 '18 09:02 agross

No. The problem is likely that the server does not correctly return the status code "503 Storage Temporarily Not Available" for said folder or even fails to mount them to the filesystem view.

The clients do not see the folders any more so they believe they are deleted so they delete it locally.

The correct behavior is to keep the mounts visible (incoming shares are mounts) but when explored they should return the 503 error.

PVince81 avatar Feb 06 '18 10:02 PVince81

OK, who should I contact about this? owncloud/core?

agross avatar Feb 06 '18 10:02 agross

It is not clear yet whether this is a core issue or LDAP. It all depends how LDAP users are exposed at the moment the server becomes unavialable.

I'd expect the users to continue existing anyway due to the oc_account tables...

... wait a minute, you didn't post your ownCloud version ? I'm talking about OC 10.0 where I expect this problem to be resolved already with the oc_accounts table which was specifically introduced to avoid this kind of problems.

Please use the issue template https://raw.githubusercontent.com/owncloud/core/master/.github/issue_template.md

PVince81 avatar Feb 06 '18 13:02 PVince81

Talking about 10.0.4. The table exists.

$ docker exec -it owncloud_mariadb_1 mysql -uroot '-psomething' -e 'select * from owncloud.oc_accounts where user_id="agross";'
+----+-------------------------+---------+---------------+----------------+-------+------------+--------------------------+---------------------------+-------+
| id | email                   | user_id | lower_user_id | display_name   | quota | last_login | backend                  | home                      | state |
+----+-------------------------+---------+---------------+----------------+-------+------------+--------------------------+---------------------------+-------+
|  1 | [email protected] | agross  | agross        | Alexander Gro� | NULL  | 1517698680 | OCA\User_LDAP\User_Proxy | /var/www/html/data/agross |     1 |
+----+-------------------------+---------+---------------+----------------+-------+------------+--------------------------+---------------------------+-------+

FYI, the issue template in core does not apply to users_ldap.

agross avatar Feb 06 '18 13:02 agross

The table should contain the users from the LDAP users that disappeared when the LDAP server went away.

Did you also setup the cron job that runs occ user:sync as per documentation ?

I wonder whether said command properly detects missing servers and doesn't try to sync the disappeared users. Maybe the cron output from that moment contains some clues ?

PVince81 avatar Feb 06 '18 13:02 PVince81

  1. I wasn't aware of occ user:sync and couldn't find any information on this doing a quick search in the admin docs, here or here. Where is that documented?
  2. I don't really care about added users that occ users:sync might add to oC, I guess sync allows to share stuff with users that never logged in, but we don't need that ATM.
  3. It's just that the LDAP server connection is interrupted that causes shares to be considered gone by either the server or the client.

agross avatar Feb 06 '18 14:02 agross

@agross you've searched in the 9.1 docs for the user:sync - you find it documented here: https://doc.owncloud.org/server/latest/admin_manual/configuration/server/occ_command.html#syncing-user-accounts-label

patrickjahns avatar Feb 06 '18 20:02 patrickjahns

@patrickjahns Thanks. As far as I understand it, syncing users is optional with a small number of users. We have about 10, which I consider small.

FYI, this is what I tried earlier today to find the docs you mentioned. And yes, I was searching the latest docs.

https://doc.owncloud.org/server/latest/admin_manual/search.html?q=user%3Async

agross avatar Feb 06 '18 21:02 agross

I just failed to reproduce this. When ldap is down A cannot login. B being a database user still can. He can also up and download files into D.

@agross What you describe sounds like B was disabled. That only happens when syncing users. Any errors in the logfile? Can you send a log file with debugging enabled? Is D a federated share?

butonic avatar Feb 12 '18 14:02 butonic

{"reqId":"5a0e0645-e8aa-49fe-b927-8f90d27e0b47",
"level":3,
"time":"2018-02-07T22:55:59+00:00",
"remoteAddr":"172.19.0.1",
"user":"agross",
"app":"user_ldap",
"method":"PROPFIND",
"url":"/remote.php/dav/files/agross/",
"message":"Exception: {"Exception":"OC\ServerNotAvailableException",
"Message":"Lost connection to LDAP server.",
"Code":0,
"Trace":"#0 /var/www/html/apps/user_ldap/lib/LDAP.php(279): OCA\User_LDAP\LDAP->postFunctionCall()\
#1 /var/www/html/apps/user_ldap/lib/LDAP.php(43): OCA\User_LDAP\LDAP->invokeLDAPMethod('bind', Resource id #70, 'uid=owncloud,cn...', 'bind password...')\
#2 /var/www/html/apps/user_ldap/lib/Connection.php(540): OCA\User_LDAP\LDAP->bind(Resource id #70, 'uid=owncloud,cn...', 'HIs$9X4ECR?!I+V...')\
#3 /var/www/html/apps/user_ldap/lib/Connection.php(167): OCA\User_LDAP\Connection->establishConnection()\
#4 /var/www/html/apps/user_ldap/lib/Connection.php(176): OCA\User_LDAP\Connection->init()\
#5 /var/www/html/apps/user_ldap/lib/Access.php(989): OCA\User_LDAP\Connection->getConnectionResource()\
#6 /var/www/html/apps/user_ldap/lib/Access.php(1156): OCA\User_LDAP\Access->executeSearch('(&(|(uid=agross...', Array, Array, NULL, NULL)\
#7 /var/www/html/apps/user_ldap/lib/Access.php(925): OCA\User_LDAP\Access->search('(&(|(uid=agross...', Array, Array, NULL, NULL)\
#8 /var/www/html/apps/user_ldap/lib/Access.php(821): OCA\User_LDAP\Access->searchUsers('(&(|(uid=agross...', Array, NULL, NULL)\
#9 /var/www/html/apps/user_ldap/lib/Access.php(794): OCA\User_LDAP\Access->fetchListOfUsers('(&(|(uid=agross...', Array)\
#10 /var/www/html/apps/user_ldap/lib/User/Manager.php(526): OCA\User_LDAP\Access->fetchUsersByLoginName('agross', Array)\
#11 /var/www/html/apps/user_ldap/lib/User_LDAP.php(140): OCA\User_LDAP\User\Manager->getLDAPUserByLoginName('agross')\
#12 [internal function]: OCA\User_LDAP\User_LDAP->checkPassword(*** sensitive parameters replaced ***)\
#13 /var/www/html/apps/user_ldap/lib/User_Proxy.php(75): call_user_func_array(Array, Array)\
#14 /var/www/html/apps/user_ldap/lib/Proxy.php(140): OCA\User_LDAP\User_Proxy->walkBackends('agross', 'checkPassword', Array)\
#15 /var/www/html/apps/user_ldap/lib/User_Proxy.php(180): OCA\User_LDAP\Proxy->handleRequest('agross', 'checkPassword', Array)\
#16 /var/www/html/lib/private/User/Manager.php(215): OCA\User_LDAP\User_Proxy->checkPassword(*** sensitive parameters replaced ***)\
#17 /var/www/html/lib/private/User/BasicAuthModule.php(49): OC\User\Manager->checkPassword(*** sensitive parameters replaced ***)\
#18 /var/www/html/lib/private/User/Session.php(883): OC\User\BasicAuthModule->auth(Object(OC\AppFramework\Http\Request))\
#19 /var/www/html/apps/dav/lib/Connector/Sabre/Auth.php(116): OC\User\Session->verifyAuthHeaders(Object(OC\AppFramework\Http\Request))\
#20 /var/www/html/lib/composer/sabre/dav/lib/DAV/Auth/Backend/AbstractBasic.php(105): OCA\DAV\Connector\Sabre\Auth->validateUserPass(*** sensitive parameters replaced ***)\
#21 /var/www/html/apps/dav/lib/Connector/Sabre/Auth.php(246): Sabre\DAV\Auth\Backend\AbstractBasic->check(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#22 /var/www/html/apps/dav/lib/Connector/Sabre/Auth.php(150): OCA\DAV\Connector\Sabre\Auth->auth(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#23 /var/www/html/lib/composer/sabre/dav/lib/DAV/Auth/Plugin.php(201): OCA\DAV\Connector\Sabre\Auth->check(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#24 /var/www/html/lib/composer/sabre/dav/lib/DAV/Auth/Plugin.php(150): Sabre\DAV\Auth\Plugin->check(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#25 [internal function]: Sabre\DAV\Auth\Plugin->beforeMethod(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#26 /var/www/html/lib/composer/sabre/event/lib/EventEmitterTrait.php(105): call_user_func_array(Array, Array)\
#27 /var/www/html/lib/composer/sabre/dav/lib/DAV/Server.php(466): Sabre\Event\EventEmitter->emit('beforeMethod', Array)\
#28 /var/www/html/lib/composer/sabre/dav/lib/DAV/Server.php(254): Sabre\DAV\Server->invokeMethod(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#29 /var/www/html/apps/dav/lib/Server.php(256): Sabre\DAV\Server->exec()\
#30 /var/www/html/apps/dav/appinfo/v2/remote.php(31): OCA\DAV\Server->exec()\
#31 /var/www/html/remote.php(165): require_once('/var/www/html/a...')\
#32 {main}",
"File":"/var/www/html/apps/user_ldap/lib/LDAP.php",
"Line":310}"}

{"reqId":"5a0e0645-e8aa-49fe-b927-8f90d27e0b47",
"level":4,
"time":"2018-02-07T22:58:10+00:00",
"remoteAddr":"172.19.0.1",
"user":"agross",
"app":"webdav",
"method":"PROPFIND",
"url":"/remote.php/dav/files/agross/",
"message":"Exception: {"Message":"HTTP/1.1 503 OC\ServerNotAvailableException: Lost connection to LDAP server.",
"Exception":"Sabre\DAV\Exception\ServiceUnavailable",
"Code":0,
"Trace":"#0 /var/www/html/lib/composer/sabre/dav/lib/DAV/Auth/Plugin.php(201): OCA\DAV\Connector\Sabre\Auth->check(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#1 /var/www/html/lib/composer/sabre/dav/lib/DAV/Auth/Plugin.php(150): Sabre\DAV\Auth\Plugin->check(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#2 [internal function]: Sabre\DAV\Auth\Plugin->beforeMethod(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#3 /var/www/html/lib/composer/sabre/event/lib/EventEmitterTrait.php(105): call_user_func_array(Array, Array)\
#4 /var/www/html/lib/composer/sabre/dav/lib/DAV/Server.php(466): Sabre\Event\EventEmitter->emit('beforeMethod', Array)\
#5 /var/www/html/lib/composer/sabre/dav/lib/DAV/Server.php(254): Sabre\DAV\Server->invokeMethod(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))\
#6 /var/www/html/apps/dav/lib/Server.php(256): Sabre\DAV\Server->exec()\
#7 /var/www/html/apps/dav/appinfo/v2/remote.php(31): OCA\DAV\Server->exec()\
#8 /var/www/html/remote.php(165): require_once('/var/www/html/a...')\
#9 {main}",
"File":"/var/www/html/apps/dav/lib/Connector/Sabre/Auth.php",
"Line":157,
"User":"agross"}"}

This is what gets logged.

What you describe sounds like B was disabled.

All I can say is that B no longer sees the share (confirmed using the web UI) and his Windows client deletes the D from disk. The share returns once LDAP is back up and A is able to login.

Is D a federated share?

No, just a normal share.

agross avatar Feb 12 '18 14:02 agross

@agross

syncing users is optional with a small number of users. We have about 10, which I consider small.

Slight caveat: if they have never logged in, they won't be available for any sharing - hence the recommendation of syncing them straight away.

patrickjahns avatar Feb 12 '18 15:02 patrickjahns

if they have never logged in, they won't be available for any sharing

I know. As I said, not a problem for us. Our user count is rather stable (changed once in a few years).

agross avatar Feb 12 '18 15:02 agross

what exact version of user_ldap are you using?

butonic avatar Feb 14 '18 13:02 butonic

user_ldap: 0.10.0

agross avatar Feb 14 '18 14:02 agross