test_key.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import, print_function, unicode_literals
  3. import ast
  4. import os
  5. import re
  6. import textwrap
  7. import pytest
  8. import salt.utils.files
  9. import salt.utils.platform
  10. import salt.utils.yaml
  11. USERA = "saltdev-key"
  12. USERA_PWD = "saltdev"
  13. HASHED_USERA_PWD = "$6$SALTsalt$ZZFD90fKFWq8AGmmX0L3uBtS9fXL62SrTk5zcnQ6EkD6zoiM3kB88G1Zvs0xm/gZ7WXJRs5nsTBybUvGSqZkT."
  14. @pytest.fixture(scope="module")
  15. def saltdev_account(sminion):
  16. try:
  17. assert sminion.functions.user.add(USERA, createhome=False)
  18. assert sminion.functions.shadow.set_password(
  19. USERA, USERA_PWD if salt.utils.platform.is_darwin() else HASHED_USERA_PWD
  20. )
  21. assert USERA in sminion.functions.user.list_users()
  22. # Run tests
  23. yield
  24. finally:
  25. sminion.functions.user.delete(USERA, remove=True)
  26. @pytest.mark.windows_whitelisted
  27. @pytest.mark.usefixtures("salt_sub_minion")
  28. class TestSaltKey(object):
  29. """
  30. Test salt-key script
  31. """
  32. def test_remove_key(self, salt_master, salt_key_cli):
  33. """
  34. test salt-key -d usage
  35. """
  36. min_name = "minibar"
  37. pki_dir = salt_master.config["pki_dir"]
  38. key = os.path.join(pki_dir, "minions", min_name)
  39. with salt.utils.files.fopen(key, "w") as fp:
  40. fp.write(
  41. textwrap.dedent(
  42. """\
  43. -----BEGIN PUBLIC KEY-----
  44. MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoqIZDtcQtqUNs0wC7qQz
  45. JwFhXAVNT5C8M8zhI+pFtF/63KoN5k1WwAqP2j3LquTG68WpxcBwLtKfd7FVA/Kr
  46. OF3kXDWFnDi+HDchW2lJObgfzLckWNRFaF8SBvFM2dys3CGSgCV0S/qxnRAjrJQb
  47. B3uQwtZ64ncJAlkYpArv3GwsfRJ5UUQnYPDEJwGzMskZ0pHd60WwM1gMlfYmNX5O
  48. RBEjybyNpYDzpda6e6Ypsn6ePGLkP/tuwUf+q9wpbRE3ZwqERC2XRPux+HX2rGP+
  49. mkzpmuHkyi2wV33A9pDfMgRHdln2CLX0KgfRGixUQhW1o+Kmfv2rq4sGwpCgLbTh
  50. NwIDAQAB
  51. -----END PUBLIC KEY-----
  52. """
  53. )
  54. )
  55. try:
  56. # Check Key
  57. ret = salt_key_cli.run("-p", min_name)
  58. assert ret.exitcode == 0
  59. assert "minions" in ret.json
  60. assert min_name in ret.json["minions"]
  61. assert "-----BEGIN PUBLIC KEY-----" in ret.json["minions"][min_name]
  62. # Remove Key
  63. ret = salt_key_cli.run("-d", min_name, "-y")
  64. assert ret.exitcode == 0
  65. # We can't load JSON because we print to stdout!
  66. # >>>>> STDOUT >>>>>
  67. # The following keys are going to be deleted:
  68. # {
  69. # "minions": [
  70. # "minibar"
  71. # ]
  72. # }
  73. # Key for minion minibar deleted.
  74. # <<<<< STDOUT <<<<<
  75. assert "minions" in ret.stdout
  76. assert min_name in ret.stdout
  77. # Check Key
  78. ret = salt_key_cli.run("-p", min_name)
  79. assert ret.exitcode == 0
  80. assert ret.json == {}
  81. finally:
  82. if os.path.exists(key):
  83. os.unlink(key)
  84. @pytest.mark.parametrize("key_type", ("acc", "pre", "den", "un", "rej"))
  85. def test_list_accepted_args(self, salt_key_cli, key_type):
  86. """
  87. test salt-key -l for accepted arguments
  88. """
  89. # Should not trigger any error
  90. ret = salt_key_cli.run("-l", key_type)
  91. assert ret.exitcode == 0
  92. assert "error:" not in ret.stdout
  93. # Should throw an error now
  94. ret = salt_key_cli.run("-l", "foo-{}".format(key_type))
  95. assert ret.exitcode != 0
  96. assert "error:" in ret.stderr
  97. def test_list_all(self, salt_key_cli):
  98. """
  99. test salt-key -L
  100. """
  101. ret = salt_key_cli.run("-L")
  102. assert ret.exitcode == 0
  103. expected = {
  104. "minions_rejected": [],
  105. "minions_denied": [],
  106. "minions_pre": [],
  107. "minions": ["minion", "sub_minion"],
  108. }
  109. assert ret.json == expected
  110. def test_list_all_yaml_out(self, salt_key_cli):
  111. """
  112. test salt-key -L --out=yaml
  113. """
  114. ret = salt_key_cli.run("-L", "--out=yaml")
  115. assert ret.exitcode == 0
  116. output = salt.utils.yaml.safe_load(ret.stdout)
  117. expected = {
  118. "minions_rejected": [],
  119. "minions_denied": [],
  120. "minions_pre": [],
  121. "minions": ["minion", "sub_minion"],
  122. }
  123. assert output == expected
  124. def test_list_all_raw_out(self, salt_key_cli):
  125. """
  126. test salt-key -L --out=raw
  127. """
  128. ret = salt_key_cli.run("-L", "--out=raw")
  129. assert ret.exitcode == 0
  130. output = ast.literal_eval(ret.stdout)
  131. expected = {
  132. "minions_rejected": [],
  133. "minions_denied": [],
  134. "minions_pre": [],
  135. "minions": ["minion", "sub_minion"],
  136. }
  137. assert output == expected
  138. def test_list_acc(self, salt_key_cli):
  139. """
  140. test salt-key -l acc
  141. """
  142. ret = salt_key_cli.run("-l", "acc")
  143. assert ret.exitcode == 0
  144. expected = {"minions": ["minion", "sub_minion"]}
  145. assert ret.json == expected
  146. @pytest.mark.skip_if_not_root
  147. @pytest.mark.destructive_test
  148. @pytest.mark.skip_on_windows(reason="PAM is not supported on Windows")
  149. def test_list_acc_eauth(self, salt_key_cli, saltdev_account):
  150. """
  151. test salt-key -l with eauth
  152. """
  153. ret = salt_key_cli.run(
  154. "-l", "acc", "--eauth", "pam", "--username", USERA, "--password", USERA_PWD
  155. )
  156. assert ret.exitcode == 0
  157. expected = {"minions": ["minion", "sub_minion"]}
  158. assert ret.json == expected
  159. @pytest.mark.skip_if_not_root
  160. @pytest.mark.destructive_test
  161. @pytest.mark.skip_on_windows(reason="PAM is not supported on Windows")
  162. def test_list_acc_eauth_bad_creds(self, salt_key_cli, saltdev_account):
  163. """
  164. test salt-key -l with eauth and bad creds
  165. """
  166. ret = salt_key_cli.run(
  167. "-l",
  168. "acc",
  169. "--eauth",
  170. "pam",
  171. "--username",
  172. USERA,
  173. "--password",
  174. "wrongpassword",
  175. )
  176. assert (
  177. ret.stdout
  178. == 'Authentication failure of type "eauth" occurred for user {}.'.format(
  179. USERA
  180. )
  181. )
  182. def test_list_acc_wrong_eauth(self, salt_key_cli):
  183. """
  184. test salt-key -l with wrong eauth
  185. """
  186. ret = salt_key_cli.run(
  187. "-l",
  188. "acc",
  189. "--eauth",
  190. "wrongeauth",
  191. "--username",
  192. USERA,
  193. "--password",
  194. USERA_PWD,
  195. )
  196. assert ret.exitcode == 0, ret
  197. assert re.search(
  198. r"^The specified external authentication system \"wrongeauth\" is not available\nAvailable eauth types: auto, .*",
  199. ret.stdout.replace("\r\n", "\n"),
  200. )
  201. def test_list_un(self, salt_key_cli):
  202. """
  203. test salt-key -l un
  204. """
  205. ret = salt_key_cli.run("-l", "un")
  206. assert ret.exitcode == 0
  207. expected = {"minions_pre": []}
  208. assert ret.json == expected
  209. def test_keys_generation(self, salt_key_cli):
  210. with pytest.helpers.temp_directory() as tempdir:
  211. ret = salt_key_cli.run("--gen-keys", "minibar", "--gen-keys-dir", tempdir)
  212. assert ret.exitcode == 0
  213. try:
  214. key_names = ("minibar.pub", "minibar.pem")
  215. for fname in key_names:
  216. assert os.path.isfile(os.path.join(tempdir, fname))
  217. finally:
  218. for filename in os.listdir(tempdir):
  219. os.chmod(os.path.join(tempdir, filename), 0o700)
  220. def test_keys_generation_keysize_min(self, salt_key_cli):
  221. with pytest.helpers.temp_directory() as tempdir:
  222. ret = salt_key_cli.run(
  223. "--gen-keys", "minibar", "--gen-keys-dir", tempdir, "--keysize", "1024"
  224. )
  225. assert ret.exitcode != 0
  226. assert "error: The minimum value for keysize is 2048" in ret.stderr
  227. def test_keys_generation_keysize_max(self, salt_key_cli):
  228. with pytest.helpers.temp_directory() as tempdir:
  229. ret = salt_key_cli.run(
  230. "--gen-keys", "minibar", "--gen-keys-dir", tempdir, "--keysize", "32769"
  231. )
  232. assert ret.exitcode != 0
  233. assert "error: The maximum value for keysize is 32768" in ret.stderr