test_wtmp.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. # coding: utf-8
  2. # Python libs
  3. from __future__ import absolute_import
  4. import datetime
  5. import logging
  6. # Salt testing libs
  7. from tests.support.unit import skipIf, TestCase
  8. from tests.support.mock import patch, MagicMock, mock_open
  9. from tests.support.mixins import LoaderModuleMockMixin
  10. # Salt libs
  11. import salt.beacons.wtmp as wtmp
  12. from salt.ext import six
  13. # pylint: disable=import-error
  14. try:
  15. import dateutil.parser as dateutil_parser # pylint: disable=unused-import
  16. _TIME_SUPPORTED = True
  17. except ImportError:
  18. _TIME_SUPPORTED = False
  19. raw = b'\x07\x00\x00\x00H\x18\x00\x00pts/14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s/14gareth\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00::1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13I\xc5YZf\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
  20. pack = (7, 6216, b'pts/14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b's/14', b'gareth\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'::1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 0, 0, 0, 1506101523, 353882, 0, 0, 0, 16777216)
  21. log = logging.getLogger(__name__)
  22. class WTMPBeaconTestCase(TestCase, LoaderModuleMockMixin):
  23. '''
  24. Test case for salt.beacons.[s]
  25. '''
  26. def setup_loader_modules(self):
  27. return {
  28. wtmp: {
  29. '__context__': {'wtmp.loc': 2},
  30. '__salt__': {},
  31. }
  32. }
  33. def test_non_list_config(self):
  34. config = {}
  35. ret = wtmp.validate(config)
  36. self.assertEqual(ret, (False, 'Configuration for wtmp beacon must'
  37. ' be a list.'))
  38. def test_empty_config(self):
  39. config = [{}]
  40. ret = wtmp.validate(config)
  41. self.assertEqual(ret, (True, 'Valid beacon configuration'))
  42. def test_no_match(self):
  43. config = [{'users': {'gareth': {'time_range': {'end': '09-22-2017 5pm',
  44. 'start': '09-22-2017 3pm'}}}}
  45. ]
  46. ret = wtmp.validate(config)
  47. self.assertEqual(ret, (True, 'Valid beacon configuration'))
  48. with patch('salt.utils.files.fopen', mock_open(b'')) as m_open:
  49. ret = wtmp.beacon(config)
  50. call_args = next(six.itervalues(m_open.filehandles))[0].call.args
  51. assert call_args == (wtmp.WTMP, 'rb'), call_args
  52. assert ret == [], ret
  53. def test_invalid_users(self):
  54. config = [{'users': ['gareth']}]
  55. ret = wtmp.validate(config)
  56. self.assertEqual(ret, (False, 'User configuration for wtmp beacon must be a dictionary.'))
  57. def test_invalid_groups(self):
  58. config = [{'groups': ['docker']}]
  59. ret = wtmp.validate(config)
  60. self.assertEqual(ret, (False, 'Group configuration for wtmp beacon must be a dictionary.'))
  61. def test_default_invalid_time_range(self):
  62. config = [{'defaults': {'time_range': {'start': '3pm'}}}]
  63. ret = wtmp.validate(config)
  64. self.assertEqual(ret, (False, 'The time_range parameter for wtmp beacon must contain start & end options.'))
  65. def test_users_invalid_time_range(self):
  66. config = [{'users': {'gareth': {'time_range': {'start': '3pm'}}}}]
  67. ret = wtmp.validate(config)
  68. self.assertEqual(ret, (False, 'The time_range parameter for wtmp beacon must contain start & end options.'))
  69. def test_groups_invalid_time_range(self):
  70. config = [{'groups': {'docker': {'time_range': {'start': '3pm'}}}}]
  71. ret = wtmp.validate(config)
  72. self.assertEqual(ret, (False, 'The time_range parameter for wtmp beacon must contain start & end options.'))
  73. def test_match(self):
  74. with patch('salt.utils.files.fopen',
  75. mock_open(read_data=raw)):
  76. with patch('struct.unpack',
  77. MagicMock(return_value=pack)):
  78. config = [{'users': {'gareth': {}}}]
  79. ret = wtmp.validate(config)
  80. self.assertEqual(ret, (True, 'Valid beacon configuration'))
  81. _expected = [{'PID': 6216,
  82. 'action': 'login',
  83. 'line': 'pts/14',
  84. 'session': 0,
  85. 'time': 0,
  86. 'exit_status': 0,
  87. 'inittab': 's/14',
  88. 'type': 7,
  89. 'addr': 1506101523,
  90. 'hostname': '::1',
  91. 'user': 'gareth'}]
  92. ret = wtmp.beacon(config)
  93. log.debug('{}'.format(ret))
  94. self.assertEqual(ret, _expected)
  95. @skipIf(not _TIME_SUPPORTED, 'dateutil.parser is missing.')
  96. def test_match_time(self):
  97. with patch('salt.utils.files.fopen',
  98. mock_open(read_data=raw)):
  99. mock_now = datetime.datetime(2017, 9, 22, 16, 0, 0, 0)
  100. with patch('datetime.datetime', MagicMock()), \
  101. patch('datetime.datetime.now',
  102. MagicMock(return_value=mock_now)):
  103. with patch('struct.unpack',
  104. MagicMock(return_value=pack)):
  105. config = [{'users': {'gareth': {'time': {'end': '09-22-2017 5pm',
  106. 'start': '09-22-2017 3pm'}}}}
  107. ]
  108. ret = wtmp.validate(config)
  109. self.assertEqual(ret, (True, 'Valid beacon configuration'))
  110. _expected = [{'PID': 6216,
  111. 'action': 'login',
  112. 'line': 'pts/14',
  113. 'session': 0,
  114. 'time': 0,
  115. 'exit_status': 0,
  116. 'inittab': 's/14',
  117. 'type': 7,
  118. 'addr': 1506101523,
  119. 'hostname': '::1',
  120. 'user': 'gareth'}]
  121. ret = wtmp.beacon(config)
  122. self.assertEqual(ret, _expected)
  123. def test_match_group(self):
  124. for groupadd in ('salt.modules.aix_group',
  125. 'salt.modules.mac_group',
  126. 'salt.modules.pw_group',
  127. 'salt.modules.solaris_group',
  128. 'salt.modules.win_groupadd'):
  129. mock_group_info = {'passwd': 'x',
  130. 'gid': 100,
  131. 'name': 'users',
  132. 'members': ['gareth']}
  133. with patch('salt.utils.files.fopen',
  134. mock_open(read_data=raw)):
  135. with patch('time.time',
  136. MagicMock(return_value=1506121200)):
  137. with patch('struct.unpack',
  138. MagicMock(return_value=pack)):
  139. with patch('{0}.info'.format(groupadd),
  140. new=MagicMock(return_value=mock_group_info)):
  141. config = [{'group': {'users': {'time': {'end': '09-22-2017 5pm',
  142. 'start': '09-22-2017 3pm'}}}}
  143. ]
  144. ret = wtmp.validate(config)
  145. self.assertEqual(ret,
  146. (True, 'Valid beacon configuration'))
  147. _expected = [{'PID': 6216,
  148. 'action': 'login',
  149. 'line': 'pts/14',
  150. 'session': 0,
  151. 'time': 0,
  152. 'exit_status': 0,
  153. 'inittab': 's/14',
  154. 'type': 7,
  155. 'addr': 1506101523,
  156. 'hostname': '::1',
  157. 'user': 'gareth'}]
  158. ret = wtmp.beacon(config)
  159. self.assertEqual(ret, _expected)