test_master.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. import salt.config
  4. import salt.master
  5. from tests.support.helpers import slowTest
  6. from tests.support.mock import MagicMock, patch
  7. from tests.support.unit import TestCase
  8. class TransportMethodsTest(TestCase):
  9. def test_transport_methods(self):
  10. class Foo(salt.master.TransportMethods):
  11. expose_methods = ["bar"]
  12. def bar(self):
  13. pass
  14. def bang(self):
  15. pass
  16. foo = Foo()
  17. assert foo.get_method("bar") is not None
  18. assert foo.get_method("bang") is None
  19. class ClearFuncsTestCase(TestCase):
  20. """
  21. TestCase for salt.master.ClearFuncs class
  22. """
  23. @classmethod
  24. def setUpClass(cls):
  25. opts = salt.config.master_config(None)
  26. cls.clear_funcs = salt.master.ClearFuncs(opts, {})
  27. @classmethod
  28. def tearDownClass(cls):
  29. del cls.clear_funcs
  30. def test_get_method(self):
  31. assert getattr(self.clear_funcs, "_send_pub", None) is not None
  32. assert self.clear_funcs.get_method("_send_pub") is None
  33. # runner tests
  34. @slowTest
  35. def test_runner_token_not_authenticated(self):
  36. """
  37. Asserts that a TokenAuthenticationError is returned when the token can't authenticate.
  38. """
  39. mock_ret = {
  40. "error": {
  41. "name": "TokenAuthenticationError",
  42. "message": 'Authentication failure of type "token" occurred.',
  43. }
  44. }
  45. ret = self.clear_funcs.runner({"token": "asdfasdfasdfasdf"})
  46. self.assertDictEqual(mock_ret, ret)
  47. @slowTest
  48. def test_runner_token_authorization_error(self):
  49. """
  50. Asserts that a TokenAuthenticationError is returned when the token authenticates, but is
  51. not authorized.
  52. """
  53. token = "asdfasdfasdfasdf"
  54. clear_load = {"token": token, "fun": "test.arg"}
  55. mock_token = {"token": token, "eauth": "foo", "name": "test"}
  56. mock_ret = {
  57. "error": {
  58. "name": "TokenAuthenticationError",
  59. "message": 'Authentication failure of type "token" occurred '
  60. "for user test.",
  61. }
  62. }
  63. with patch(
  64. "salt.auth.LoadAuth.authenticate_token", MagicMock(return_value=mock_token)
  65. ), patch("salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=[])):
  66. ret = self.clear_funcs.runner(clear_load)
  67. self.assertDictEqual(mock_ret, ret)
  68. @slowTest
  69. def test_runner_token_salt_invocation_error(self):
  70. """
  71. Asserts that a SaltInvocationError is returned when the token authenticates, but the
  72. command is malformed.
  73. """
  74. token = "asdfasdfasdfasdf"
  75. clear_load = {"token": token, "fun": "badtestarg"}
  76. mock_token = {"token": token, "eauth": "foo", "name": "test"}
  77. mock_ret = {
  78. "error": {
  79. "name": "SaltInvocationError",
  80. "message": "A command invocation error occurred: Check syntax.",
  81. }
  82. }
  83. with patch(
  84. "salt.auth.LoadAuth.authenticate_token", MagicMock(return_value=mock_token)
  85. ), patch(
  86. "salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=["testing"])
  87. ):
  88. ret = self.clear_funcs.runner(clear_load)
  89. self.assertDictEqual(mock_ret, ret)
  90. @slowTest
  91. def test_runner_eauth_not_authenticated(self):
  92. """
  93. Asserts that an EauthAuthenticationError is returned when the user can't authenticate.
  94. """
  95. mock_ret = {
  96. "error": {
  97. "name": "EauthAuthenticationError",
  98. "message": 'Authentication failure of type "eauth" occurred for '
  99. "user UNKNOWN.",
  100. }
  101. }
  102. ret = self.clear_funcs.runner({"eauth": "foo"})
  103. self.assertDictEqual(mock_ret, ret)
  104. @slowTest
  105. def test_runner_eauth_authorization_error(self):
  106. """
  107. Asserts that an EauthAuthenticationError is returned when the user authenticates, but is
  108. not authorized.
  109. """
  110. clear_load = {"eauth": "foo", "username": "test", "fun": "test.arg"}
  111. mock_ret = {
  112. "error": {
  113. "name": "EauthAuthenticationError",
  114. "message": 'Authentication failure of type "eauth" occurred for '
  115. "user test.",
  116. }
  117. }
  118. with patch(
  119. "salt.auth.LoadAuth.authenticate_eauth", MagicMock(return_value=True)
  120. ), patch("salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=[])):
  121. ret = self.clear_funcs.runner(clear_load)
  122. self.assertDictEqual(mock_ret, ret)
  123. @slowTest
  124. def test_runner_eauth_salt_invocation_error(self):
  125. """
  126. Asserts that an EauthAuthenticationError is returned when the user authenticates, but the
  127. command is malformed.
  128. """
  129. clear_load = {"eauth": "foo", "username": "test", "fun": "bad.test.arg.func"}
  130. mock_ret = {
  131. "error": {
  132. "name": "SaltInvocationError",
  133. "message": "A command invocation error occurred: Check syntax.",
  134. }
  135. }
  136. with patch(
  137. "salt.auth.LoadAuth.authenticate_eauth", MagicMock(return_value=True)
  138. ), patch(
  139. "salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=["testing"])
  140. ):
  141. ret = self.clear_funcs.runner(clear_load)
  142. self.assertDictEqual(mock_ret, ret)
  143. @slowTest
  144. def test_runner_user_not_authenticated(self):
  145. """
  146. Asserts that an UserAuthenticationError is returned when the user can't authenticate.
  147. """
  148. mock_ret = {
  149. "error": {
  150. "name": "UserAuthenticationError",
  151. "message": 'Authentication failure of type "user" occurred',
  152. }
  153. }
  154. ret = self.clear_funcs.runner({})
  155. self.assertDictEqual(mock_ret, ret)
  156. # wheel tests
  157. @slowTest
  158. def test_wheel_token_not_authenticated(self):
  159. """
  160. Asserts that a TokenAuthenticationError is returned when the token can't authenticate.
  161. """
  162. mock_ret = {
  163. "error": {
  164. "name": "TokenAuthenticationError",
  165. "message": 'Authentication failure of type "token" occurred.',
  166. }
  167. }
  168. ret = self.clear_funcs.wheel({"token": "asdfasdfasdfasdf"})
  169. self.assertDictEqual(mock_ret, ret)
  170. @slowTest
  171. def test_wheel_token_authorization_error(self):
  172. """
  173. Asserts that a TokenAuthenticationError is returned when the token authenticates, but is
  174. not authorized.
  175. """
  176. token = "asdfasdfasdfasdf"
  177. clear_load = {"token": token, "fun": "test.arg"}
  178. mock_token = {"token": token, "eauth": "foo", "name": "test"}
  179. mock_ret = {
  180. "error": {
  181. "name": "TokenAuthenticationError",
  182. "message": 'Authentication failure of type "token" occurred '
  183. "for user test.",
  184. }
  185. }
  186. with patch(
  187. "salt.auth.LoadAuth.authenticate_token", MagicMock(return_value=mock_token)
  188. ), patch("salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=[])):
  189. ret = self.clear_funcs.wheel(clear_load)
  190. self.assertDictEqual(mock_ret, ret)
  191. @slowTest
  192. def test_wheel_token_salt_invocation_error(self):
  193. """
  194. Asserts that a SaltInvocationError is returned when the token authenticates, but the
  195. command is malformed.
  196. """
  197. token = "asdfasdfasdfasdf"
  198. clear_load = {"token": token, "fun": "badtestarg"}
  199. mock_token = {"token": token, "eauth": "foo", "name": "test"}
  200. mock_ret = {
  201. "error": {
  202. "name": "SaltInvocationError",
  203. "message": "A command invocation error occurred: Check syntax.",
  204. }
  205. }
  206. with patch(
  207. "salt.auth.LoadAuth.authenticate_token", MagicMock(return_value=mock_token)
  208. ), patch(
  209. "salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=["testing"])
  210. ):
  211. ret = self.clear_funcs.wheel(clear_load)
  212. self.assertDictEqual(mock_ret, ret)
  213. @slowTest
  214. def test_wheel_eauth_not_authenticated(self):
  215. """
  216. Asserts that an EauthAuthenticationError is returned when the user can't authenticate.
  217. """
  218. mock_ret = {
  219. "error": {
  220. "name": "EauthAuthenticationError",
  221. "message": 'Authentication failure of type "eauth" occurred for '
  222. "user UNKNOWN.",
  223. }
  224. }
  225. ret = self.clear_funcs.wheel({"eauth": "foo"})
  226. self.assertDictEqual(mock_ret, ret)
  227. @slowTest
  228. def test_wheel_eauth_authorization_error(self):
  229. """
  230. Asserts that an EauthAuthenticationError is returned when the user authenticates, but is
  231. not authorized.
  232. """
  233. clear_load = {"eauth": "foo", "username": "test", "fun": "test.arg"}
  234. mock_ret = {
  235. "error": {
  236. "name": "EauthAuthenticationError",
  237. "message": 'Authentication failure of type "eauth" occurred for '
  238. "user test.",
  239. }
  240. }
  241. with patch(
  242. "salt.auth.LoadAuth.authenticate_eauth", MagicMock(return_value=True)
  243. ), patch("salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=[])):
  244. ret = self.clear_funcs.wheel(clear_load)
  245. self.assertDictEqual(mock_ret, ret)
  246. @slowTest
  247. def test_wheel_eauth_salt_invocation_error(self):
  248. """
  249. Asserts that an EauthAuthenticationError is returned when the user authenticates, but the
  250. command is malformed.
  251. """
  252. clear_load = {"eauth": "foo", "username": "test", "fun": "bad.test.arg.func"}
  253. mock_ret = {
  254. "error": {
  255. "name": "SaltInvocationError",
  256. "message": "A command invocation error occurred: Check syntax.",
  257. }
  258. }
  259. with patch(
  260. "salt.auth.LoadAuth.authenticate_eauth", MagicMock(return_value=True)
  261. ), patch(
  262. "salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=["testing"])
  263. ):
  264. ret = self.clear_funcs.wheel(clear_load)
  265. self.assertDictEqual(mock_ret, ret)
  266. @slowTest
  267. def test_wheel_user_not_authenticated(self):
  268. """
  269. Asserts that an UserAuthenticationError is returned when the user can't authenticate.
  270. """
  271. mock_ret = {
  272. "error": {
  273. "name": "UserAuthenticationError",
  274. "message": 'Authentication failure of type "user" occurred',
  275. }
  276. }
  277. ret = self.clear_funcs.wheel({})
  278. self.assertDictEqual(mock_ret, ret)
  279. # publish tests
  280. @slowTest
  281. def test_publish_user_is_blacklisted(self):
  282. """
  283. Asserts that an AuthorizationError is returned when the user has been blacklisted.
  284. """
  285. mock_ret = {
  286. "error": {
  287. "name": "AuthorizationError",
  288. "message": "Authorization error occurred.",
  289. }
  290. }
  291. with patch(
  292. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=True)
  293. ):
  294. self.assertEqual(
  295. mock_ret, self.clear_funcs.publish({"user": "foo", "fun": "test.arg"})
  296. )
  297. @slowTest
  298. def test_publish_cmd_blacklisted(self):
  299. """
  300. Asserts that an AuthorizationError is returned when the command has been blacklisted.
  301. """
  302. mock_ret = {
  303. "error": {
  304. "name": "AuthorizationError",
  305. "message": "Authorization error occurred.",
  306. }
  307. }
  308. with patch(
  309. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  310. ), patch(
  311. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=True)
  312. ):
  313. self.assertEqual(
  314. mock_ret, self.clear_funcs.publish({"user": "foo", "fun": "test.arg"})
  315. )
  316. @slowTest
  317. def test_publish_token_not_authenticated(self):
  318. """
  319. Asserts that an AuthenticationError is returned when the token can't authenticate.
  320. """
  321. mock_ret = {
  322. "error": {
  323. "name": "AuthenticationError",
  324. "message": "Authentication error occurred.",
  325. }
  326. }
  327. load = {
  328. "user": "foo",
  329. "fun": "test.arg",
  330. "tgt": "test_minion",
  331. "kwargs": {"token": "asdfasdfasdfasdf"},
  332. }
  333. with patch(
  334. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  335. ), patch(
  336. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  337. ):
  338. self.assertEqual(mock_ret, self.clear_funcs.publish(load))
  339. @slowTest
  340. def test_publish_token_authorization_error(self):
  341. """
  342. Asserts that an AuthorizationError is returned when the token authenticates, but is not
  343. authorized.
  344. """
  345. token = "asdfasdfasdfasdf"
  346. load = {
  347. "user": "foo",
  348. "fun": "test.arg",
  349. "tgt": "test_minion",
  350. "arg": "bar",
  351. "kwargs": {"token": token},
  352. }
  353. mock_token = {"token": token, "eauth": "foo", "name": "test"}
  354. mock_ret = {
  355. "error": {
  356. "name": "AuthorizationError",
  357. "message": "Authorization error occurred.",
  358. }
  359. }
  360. with patch(
  361. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  362. ), patch(
  363. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  364. ), patch(
  365. "salt.auth.LoadAuth.authenticate_token", MagicMock(return_value=mock_token)
  366. ), patch(
  367. "salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=[])
  368. ):
  369. self.assertEqual(mock_ret, self.clear_funcs.publish(load))
  370. @slowTest
  371. def test_publish_eauth_not_authenticated(self):
  372. """
  373. Asserts that an AuthenticationError is returned when the user can't authenticate.
  374. """
  375. load = {
  376. "user": "test",
  377. "fun": "test.arg",
  378. "tgt": "test_minion",
  379. "kwargs": {"eauth": "foo"},
  380. }
  381. mock_ret = {
  382. "error": {
  383. "name": "AuthenticationError",
  384. "message": "Authentication error occurred.",
  385. }
  386. }
  387. with patch(
  388. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  389. ), patch(
  390. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  391. ):
  392. self.assertEqual(mock_ret, self.clear_funcs.publish(load))
  393. @slowTest
  394. def test_publish_eauth_authorization_error(self):
  395. """
  396. Asserts that an AuthorizationError is returned when the user authenticates, but is not
  397. authorized.
  398. """
  399. load = {
  400. "user": "test",
  401. "fun": "test.arg",
  402. "tgt": "test_minion",
  403. "kwargs": {"eauth": "foo"},
  404. "arg": "bar",
  405. }
  406. mock_ret = {
  407. "error": {
  408. "name": "AuthorizationError",
  409. "message": "Authorization error occurred.",
  410. }
  411. }
  412. with patch(
  413. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  414. ), patch(
  415. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  416. ), patch(
  417. "salt.auth.LoadAuth.authenticate_eauth", MagicMock(return_value=True)
  418. ), patch(
  419. "salt.auth.LoadAuth.get_auth_list", MagicMock(return_value=[])
  420. ):
  421. self.assertEqual(mock_ret, self.clear_funcs.publish(load))
  422. @slowTest
  423. def test_publish_user_not_authenticated(self):
  424. """
  425. Asserts that an AuthenticationError is returned when the user can't authenticate.
  426. """
  427. load = {"user": "test", "fun": "test.arg", "tgt": "test_minion"}
  428. mock_ret = {
  429. "error": {
  430. "name": "AuthenticationError",
  431. "message": "Authentication error occurred.",
  432. }
  433. }
  434. with patch(
  435. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  436. ), patch(
  437. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  438. ):
  439. self.assertEqual(mock_ret, self.clear_funcs.publish(load))
  440. @slowTest
  441. def test_publish_user_authenticated_missing_auth_list(self):
  442. """
  443. Asserts that an AuthenticationError is returned when the user has an effective user id and is
  444. authenticated, but the auth_list is empty.
  445. """
  446. load = {
  447. "user": "test",
  448. "fun": "test.arg",
  449. "tgt": "test_minion",
  450. "kwargs": {"user": "test"},
  451. "arg": "foo",
  452. }
  453. mock_ret = {
  454. "error": {
  455. "name": "AuthenticationError",
  456. "message": "Authentication error occurred.",
  457. }
  458. }
  459. with patch(
  460. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  461. ), patch(
  462. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  463. ), patch(
  464. "salt.auth.LoadAuth.authenticate_key",
  465. MagicMock(return_value="fake-user-key"),
  466. ), patch(
  467. "salt.utils.master.get_values_of_matching_keys", MagicMock(return_value=[])
  468. ):
  469. self.assertEqual(mock_ret, self.clear_funcs.publish(load))
  470. @slowTest
  471. def test_publish_user_authorization_error(self):
  472. """
  473. Asserts that an AuthorizationError is returned when the user authenticates, but is not
  474. authorized.
  475. """
  476. load = {
  477. "user": "test",
  478. "fun": "test.arg",
  479. "tgt": "test_minion",
  480. "kwargs": {"user": "test"},
  481. "arg": "foo",
  482. }
  483. mock_ret = {
  484. "error": {
  485. "name": "AuthorizationError",
  486. "message": "Authorization error occurred.",
  487. }
  488. }
  489. with patch(
  490. "salt.acl.PublisherACL.user_is_blacklisted", MagicMock(return_value=False)
  491. ), patch(
  492. "salt.acl.PublisherACL.cmd_is_blacklisted", MagicMock(return_value=False)
  493. ), patch(
  494. "salt.auth.LoadAuth.authenticate_key",
  495. MagicMock(return_value="fake-user-key"),
  496. ), patch(
  497. "salt.utils.master.get_values_of_matching_keys",
  498. MagicMock(return_value=["test"]),
  499. ), patch(
  500. "salt.utils.minions.CkMinions.auth_check", MagicMock(return_value=False)
  501. ):
  502. self.assertEqual(mock_ret, self.clear_funcs.publish(load))