test_auth.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # -*- coding: utf-8 -*-
  2. """
  3. tests.integration.shell.auth
  4. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. """
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import logging
  8. import random
  9. import string
  10. import pytest
  11. import salt.utils.platform
  12. from salt.ext.six.moves import range
  13. from salt.utils.pycrypto import gen_hash
  14. from tests.support.case import ModuleCase, ShellCase
  15. from tests.support.helpers import (
  16. destructiveTest,
  17. requires_salt_modules,
  18. requires_salt_states,
  19. skip_if_not_root,
  20. )
  21. from tests.support.mixins import SaltReturnAssertsMixin
  22. from tests.support.unit import skipIf
  23. try:
  24. import pwd
  25. import grp
  26. except ImportError:
  27. pwd, grp = None, None
  28. log = logging.getLogger(__name__)
  29. def gen_password():
  30. """
  31. generate a password and hash it
  32. """
  33. password = "".join(
  34. random.choice(string.ascii_letters + string.digits) for _ in range(20)
  35. )
  36. hashed_pwd = gen_hash("salt", password, "sha512")
  37. return password, hashed_pwd
  38. @requires_salt_states("user.absent", "user.present")
  39. @requires_salt_modules("shadow.set_password")
  40. @skip_if_not_root
  41. @skipIf(pwd is None or grp is None, "No pwd or grp module available")
  42. @destructiveTest
  43. @pytest.mark.windows_whitelisted
  44. class UserAuthTest(ModuleCase, SaltReturnAssertsMixin, ShellCase):
  45. """
  46. Test user auth mechanisms
  47. """
  48. _call_binary_ = "salt"
  49. user = "saltdev"
  50. def setUp(self):
  51. ret = self.run_state("user.present", name=self.user, createhome=False)
  52. self.assertSaltTrueReturn(ret)
  53. def tearDown(self):
  54. ret = self.run_state("user.absent", name=self.user)
  55. self.assertSaltTrueReturn(ret)
  56. @skipIf(True, "SLOWTEST skip")
  57. def test_pam_auth_valid_user(self):
  58. """
  59. test that pam auth mechanism works with a valid user
  60. """
  61. password, hashed_pwd = gen_password()
  62. # set user password
  63. set_pw_cmd = "shadow.set_password {0} '{1}'".format(
  64. self.user, password if salt.utils.platform.is_darwin() else hashed_pwd
  65. )
  66. self.assertRunCall(set_pw_cmd)
  67. # test user auth against pam
  68. cmd = '-a pam "*" test.ping --username {0} --password {1}'.format(
  69. self.user, password
  70. )
  71. resp = self.run_salt(cmd)
  72. log.debug("resp = %s", resp)
  73. self.assertIn("minion", [r.strip(": ") for r in resp])
  74. @skipIf(True, "SLOWTEST skip")
  75. def test_pam_auth_invalid_user(self):
  76. """
  77. test pam auth mechanism errors for an invalid user
  78. """
  79. cmd = '-a pam "*" test.ping ' "--username nouser --password {0}".format(
  80. "abcd1234"
  81. )
  82. resp = self.run_salt(cmd)
  83. self.assertIn("Authentication error occurred", "".join(resp))
  84. @requires_salt_states("group.absent", "group.present", "user.absent", "user.present")
  85. @requires_salt_modules("shadow.set_password", "user.chgroups")
  86. @skip_if_not_root
  87. @skipIf(pwd is None or grp is None, "No crypt module available")
  88. @destructiveTest
  89. class GroupAuthTest(ModuleCase, SaltReturnAssertsMixin, ShellCase):
  90. """
  91. Test group auth mechanisms
  92. """
  93. _call_binary_ = "salt"
  94. user = "saltadm"
  95. group = "saltops"
  96. def setUp(self):
  97. ret = self.run_state("group.present", name=self.group)
  98. self.assertSaltTrueReturn(ret)
  99. ret = self.run_state(
  100. "user.present", name=self.user, createhome=False, groups=[self.group]
  101. )
  102. self.assertSaltTrueReturn(ret)
  103. self.assertRunCall(
  104. "user.chgroups {0} {1} True".format(self.user, self.group), local=True
  105. )
  106. def tearDown(self):
  107. ret0 = self.run_state("user.absent", name=self.user)
  108. ret1 = self.run_state("group.absent", name=self.group)
  109. self.assertSaltTrueReturn(ret0)
  110. self.assertSaltTrueReturn(ret1)
  111. @skipIf(True, "SLOWTEST skip")
  112. def test_pam_auth_valid_group(self):
  113. """
  114. test that pam auth mechanism works for a valid group
  115. """
  116. password, hashed_pwd = gen_password()
  117. # set user password
  118. set_pw_cmd = "shadow.set_password {0} '{1}'".format(
  119. self.user, password if salt.utils.platform.is_darwin() else hashed_pwd
  120. )
  121. self.assertRunCall(set_pw_cmd)
  122. # test group auth against pam: saltadm is not configured in
  123. # external_auth, but saltops is and saldadm is a member of saltops
  124. cmd = '-a pam "*" test.ping --username {0} --password {1}'.format(
  125. self.user, password
  126. )
  127. resp = self.run_salt(cmd)
  128. self.assertIn("minion", [r.strip(": ") for r in resp])