ExceptionOnLostConnection.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\User_LDAP\Tests\Integration;
  8. use OC\ServerNotAvailableException;
  9. use OCA\User_LDAP\LDAP;
  10. /**
  11. * Class ExceptionOnLostConnection
  12. *
  13. * integration test, ensures that an exception is thrown, when the connection is lost.
  14. *
  15. * LDAP must be available via toxiproxy.
  16. *
  17. * This test must be run manually.
  18. *
  19. */
  20. class ExceptionOnLostConnection {
  21. /** @var string */
  22. private $ldapHost;
  23. /** @var LDAP */
  24. private $ldap;
  25. /** @var bool */
  26. private $originalProxyState;
  27. /**
  28. * @param string $toxiProxyHost host of toxiproxy as url, like http://localhost:8474
  29. * @param string $toxiProxyName name of the LDAP proxy service as configured in toxiProxy
  30. * @param string $ldapBase any valid LDAP base DN
  31. * @param null $ldapBindDN optional, bind DN if anonymous bind is not possible
  32. * @param null $ldapBindPwd optional
  33. */
  34. public function __construct(
  35. private $toxiProxyHost,
  36. private $toxiProxyName,
  37. private $ldapBase,
  38. private $ldapBindDN = null,
  39. private $ldapBindPwd = null,
  40. ) {
  41. $this->setUp();
  42. }
  43. /**
  44. * destructor
  45. */
  46. public function __destruct() {
  47. $this->cleanUp();
  48. }
  49. /**
  50. * prepares everything for the test run. Includes loading Nextcloud and
  51. * the LDAP backend, as well as getting information about toxiproxy.
  52. * Also creates an instance of the LDAP class, the testee
  53. *
  54. * @throws \Exception
  55. */
  56. public function setUp(): void {
  57. require_once __DIR__ . '/../../../../lib/base.php';
  58. \OC_App::loadApps(['user_ldap']);
  59. $ch = $this->getCurl();
  60. $proxyInfoJson = curl_exec($ch);
  61. $this->checkCurlResult($ch, $proxyInfoJson);
  62. $proxyInfo = json_decode($proxyInfoJson, true);
  63. $this->originalProxyState = $proxyInfo['enabled'];
  64. $this->ldapHost = 'ldap://' . $proxyInfo['listen']; // contains port as well
  65. $this->ldap = new LDAP();
  66. }
  67. /**
  68. * restores original state of the LDAP proxy, if necessary
  69. */
  70. public function cleanUp() {
  71. if ($this->originalProxyState === true) {
  72. $this->setProxyState(true);
  73. }
  74. }
  75. /**
  76. * runs the test and prints the result. Exit code is 0 if successful, 1 on
  77. * fail
  78. */
  79. public function run() {
  80. if ($this->originalProxyState === false) {
  81. $this->setProxyState(true);
  82. }
  83. //host contains port, 2nd parameter will be ignored
  84. $cr = $this->ldap->connect($this->ldapHost, 0);
  85. $this->ldap->bind($cr, $this->ldapBindDN, $this->ldapBindPwd);
  86. $this->ldap->search($cr, $this->ldapBase, 'objectClass=*', ['dn'], true, 5);
  87. // disable LDAP, will cause lost connection
  88. $this->setProxyState(false);
  89. try {
  90. $this->ldap->search($cr, $this->ldapBase, 'objectClass=*', ['dn'], true, 5);
  91. } catch (ServerNotAvailableException $e) {
  92. print('Test PASSED' . PHP_EOL);
  93. exit(0);
  94. }
  95. print('Test FAILED' . PHP_EOL);
  96. exit(1);
  97. }
  98. /**
  99. * tests whether a curl operation ran successfully. If not, an exception
  100. * is thrown
  101. *
  102. * @param resource|\CurlHandle $ch
  103. * @param mixed $result
  104. * @throws \Exception
  105. */
  106. private function checkCurlResult($ch, $result) {
  107. if ($result === false) {
  108. $error = curl_error($ch);
  109. curl_close($ch);
  110. throw new \Exception($error);
  111. }
  112. }
  113. /**
  114. * enables or disabled the LDAP proxy service in toxiproxy
  115. *
  116. * @param bool $isEnabled whether is should be enabled or disables
  117. * @throws \Exception
  118. */
  119. private function setProxyState($isEnabled) {
  120. if (!is_bool($isEnabled)) {
  121. throw new \InvalidArgumentException('Bool expected');
  122. }
  123. $postData = json_encode(['enabled' => $isEnabled]);
  124. $ch = $this->getCurl();
  125. curl_setopt($ch, CURLOPT_POST, true);
  126. curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  127. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  128. 'Content-Type: application/json',
  129. 'Content-Length: ' . strlen($postData)]
  130. );
  131. $recvd = curl_exec($ch);
  132. $this->checkCurlResult($ch, $recvd);
  133. }
  134. /**
  135. * initializes a curl handler towards the toxiproxy LDAP proxy service
  136. * @return resource|\CurlHandle
  137. */
  138. private function getCurl() {
  139. $ch = curl_init();
  140. curl_setopt($ch, CURLOPT_URL, $this->toxiProxyHost . '/proxies/' . $this->toxiProxyName);
  141. curl_setopt($ch, CURLOPT_HEADER, false);
  142. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  143. return $ch;
  144. }
  145. }
  146. $test = new ExceptionOnLostConnection('http://localhost:8474', 'ldap', 'dc=owncloud,dc=bzoc');
  147. $test->run();