test_salt_key.py 9.2 KB

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