ExceptionOnLostConnection.php 4.6 KB

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