/neatx/test/python/neatx.auth_test.py

http://neatx.googlecode.com/ · Python · 221 lines · 173 code · 29 blank · 19 comment · 6 complexity · 78c5fb03aa624bd100994103a8fc4916 MD5 · raw file

  1. #!/usr/bin/python
  2. #
  3. # Copyright (C) 2009 Google Inc.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18. # 02110-1301, USA.
  19. """Script for unittesting the auth module"""
  20. import os
  21. import re
  22. import tempfile
  23. import unittest
  24. from neatx import auth
  25. from neatx import constants
  26. from neatx import errors
  27. from neatx import utils
  28. DUMMY_USER = "dummyuser"
  29. DUMMY_USER2 = "anotheruser"
  30. DUMMY_PASSWORD = "Pa$$W0rd"
  31. DUMMY_PASSWORD2 = "something"
  32. def _WriteAuthScript(confirmation):
  33. (fd, name) = tempfile.mkstemp()
  34. try:
  35. os.chmod(name, 0700)
  36. try:
  37. def w(*args):
  38. for i in args:
  39. os.write(fd, i)
  40. os.write(fd, "\n")
  41. w("#!", constants.BASH)
  42. w("DUMMY_USER='", DUMMY_USER, "'")
  43. w("DUMMY_PASSWORD='", DUMMY_PASSWORD, "'")
  44. w("user=$1; shift")
  45. w("if [[ \"$user\" != \"$DUMMY_USER\" ]]; then")
  46. w(" echo 'Unknown user'")
  47. w(" exit 1")
  48. w("fi")
  49. w("read -s -p 'Password: ' pw < /dev/tty")
  50. w("echo")
  51. w("if [[ \"$pw\" != \"$DUMMY_PASSWORD\" ]]; then")
  52. w(" echo 'Authentication failed'")
  53. w(" exit 1")
  54. w("fi")
  55. if confirmation:
  56. w("echo Authentication successful")
  57. w("exec \"$@\"")
  58. finally:
  59. os.close(fd)
  60. except:
  61. utils.RemoveFile(name)
  62. raise
  63. return name
  64. class _DummyPasswordAuth:
  65. def __init__(self, cfg):
  66. pass
  67. class _DummyLdapAuth:
  68. def __init__(self, cfg):
  69. pass
  70. class _DummyAuth(auth._ExpectAuthBase):
  71. def __init__(self, cfg, authcmd, stdout_fileno, stdin_fileno):
  72. auth._ExpectAuthBase.__init__(self, cfg,
  73. stdout_fileno=stdout_fileno,
  74. stdin_fileno=stdin_fileno)
  75. self._authcmd = authcmd
  76. def GetCommand(self, username, args):
  77. return [self._authcmd, username] + args
  78. def GetPasswordPrompt(self):
  79. return re.compile(r"^Password:\s*", re.I)
  80. def _GetFdCopyPath(self):
  81. return "src/fdcopy"
  82. def _GetTtySetupPath(self):
  83. return "src/ttysetup"
  84. class _FakeAuthConfig:
  85. def __init__(self, auth_method):
  86. self.auth_method = auth_method
  87. self.auth_ssh_host = "localhost"
  88. self.auth_ssh_port = 22
  89. self.su = constants.SU
  90. self.ssh = constants.SSH
  91. class TestGetAuthenticator(unittest.TestCase):
  92. """Tests for GetAuthenticator"""
  93. def test(self):
  94. dummy_map = {
  95. "password": _DummyPasswordAuth,
  96. "ldap": _DummyLdapAuth,
  97. }
  98. authenticator = auth.GetAuthenticator(_FakeAuthConfig("password"),
  99. _method_map=dummy_map)
  100. self.failUnless(isinstance(authenticator, _DummyPasswordAuth))
  101. self.failIf(isinstance(authenticator, _DummyLdapAuth))
  102. authenticator = auth.GetAuthenticator(_FakeAuthConfig("ldap"),
  103. _method_map=dummy_map)
  104. self.failUnless(isinstance(authenticator, _DummyLdapAuth))
  105. self.failIf(isinstance(authenticator, _DummyPasswordAuth))
  106. self.failUnlessRaises(errors.UnknownAuthMethod, auth.GetAuthenticator,
  107. _FakeAuthConfig("nonexisting"),
  108. _method_map=dummy_map)
  109. class TestExpectAuthBase(unittest.TestCase):
  110. """Tests for _ExpectAuthBase"""
  111. def testGetCommand(self):
  112. cfg = _FakeAuthConfig("dummy")
  113. username = "NXtestNX"
  114. command = "/NX/test/NX"
  115. for (cls, wanted_arg0) in [(auth.SuAuth, constants.SU),
  116. (auth.SshAuth, constants.SSH)]:
  117. args = cls(cfg).GetCommand(username, [command, "a", "b"])
  118. self.failUnlessEqual(args[0], wanted_arg0)
  119. self.failUnless(username in args)
  120. self.failUnless(filter(lambda value: ("%s a b" % command) in value,
  121. args))
  122. def testAuth(self):
  123. authcmd = _WriteAuthScript(False)
  124. try:
  125. nullfile = tempfile.TemporaryFile()
  126. input = tempfile.TemporaryFile()
  127. cfg = _FakeAuthConfig("dummy")
  128. authenticator = _DummyAuth(cfg, authcmd, nullfile.fileno(),
  129. input.fileno())
  130. authenticator.AuthenticateAndRun(DUMMY_USER, DUMMY_PASSWORD,
  131. ["/bin/echo", "NX> "])
  132. authenticator.AuthenticateAndRun(DUMMY_USER, DUMMY_PASSWORD,
  133. ["/bin/echo", "NX> 105"])
  134. self.failUnlessRaises(errors.AuthFailedError,
  135. authenticator.AuthenticateAndRun,
  136. DUMMY_USER, DUMMY_PASSWORD2,
  137. ["/bin/echo", "NX> 105"])
  138. self.failUnlessRaises(errors.AuthFailedError,
  139. authenticator.AuthenticateAndRun,
  140. DUMMY_USER2, DUMMY_PASSWORD,
  141. ["/bin/echo", "NX> 105"])
  142. self.failUnlessRaises(errors.AuthFailedError,
  143. authenticator.AuthenticateAndRun,
  144. DUMMY_USER, DUMMY_PASSWORD,
  145. ["/bin/echo", "ERROR"])
  146. finally:
  147. utils.RemoveFile(authcmd)
  148. def testAuthOutput(self):
  149. expected = "NX> 105\n" + (1000 * "Hello World\n")
  150. cmd = ("set -e;"
  151. "echo 'NX> 105';"
  152. "for ((i=0; i<1000; ++i)); do"
  153. " echo 'Hello World';"
  154. "done")
  155. for confirmation in [False, True]:
  156. dummyout = tempfile.TemporaryFile()
  157. input = tempfile.TemporaryFile()
  158. cfg = _FakeAuthConfig("dummy")
  159. authcmd = _WriteAuthScript(confirmation)
  160. try:
  161. authenticator = _DummyAuth(cfg, authcmd, dummyout.fileno(),
  162. input.fileno())
  163. authenticator.AuthenticateAndRun(DUMMY_USER, DUMMY_PASSWORD,
  164. [constants.BASH, "-c", cmd])
  165. finally:
  166. utils.RemoveFile(authcmd)
  167. os.lseek(dummyout.fileno(), 0, 0)
  168. data = os.read(dummyout.fileno(), len(expected) * 2)
  169. self.failUnlessEqual(data, expected)
  170. if __name__ == '__main__':
  171. unittest.main()