test_api.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. from __future__ import unicode_literals
  2. import base64
  3. from django.contrib.auth.models import User
  4. from django.urls import reverse
  5. from rest_framework import status
  6. from rest_framework.test import APITestCase
  7. from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
  8. from secrets.models import Secret, SecretRole, SessionKey, UserKey
  9. from users.models import Token
  10. from utilities.tests import HttpStatusMixin
  11. # Dummy RSA key pair for testing use only
  12. PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
  13. MIIEowIBAAKCAQEA97wPWxpq5cClRu8Ssq609ZLfyx6E8ln/v/PdFZ7fxxmA4k+z
  14. 1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqdd453d1eY95xYVbFrIHs7yJy8lcDR
  15. 2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIbRjA2wmt2PVT26YbOX2qCMItV1+me
  16. o/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhhGY2b4PKuSTcsYjbg8adOGzFL9RXL
  17. I1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN5ZEEz+sIdlMPCAACaZAY/t9Kd/Lx
  18. Hr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xlqQIDAQABAoIBAQC4pDQVxNTTtQf6
  19. nImlH83EEto1++M+9pFFsi6fxLApJvsGsjzomke1Dy7uN93qVGk8rq3enzSYU58f
  20. sSs8BVKkH00vZ9ydAKxeAkREC1V9qkRsoTBHUY47sJcDkyZyssxfLNm7w0Q70h7a
  21. mLVEJBqr75eAxLN19vOpDk6Wkz3Bi0Dj27HLeme3hH5jLVQIIswWZnUDP3r/sdM/
  22. WA2GjoycPbug0r1FVZnxkFCrQ5yMfH3VzKBelj7356+5sc/TUXedDFN/DV2b90Ll
  23. +au7EEXecFYZwmX3SX2hpe6IWEpUW3B0fvm+Ipm8h7x68i7J0oi9EUXW2+UQYfOx
  24. dDLxTLvhAoGBAPtJJox4XcpzipSAzKxyV8K9ikUZCG2wJU7VHyZ5zpSXwl/husls
  25. brAzHQcnWayhxxuWeiQ6pLnRFPFXjlOH2FZqHXSLnfpDaymEksDPvo9GqRE3Q+F+
  26. lDRn72H1NLIj3Y3t5SwWRB34Dhy+gd5Ht9L3dCTH8cYvJGnmS4sH/z0NAoGBAPxh
  27. 2rhS1B0S9mqqvpduUPxqUIWaztXaHC6ZikloOFcgVMdh9MRrpa2sa+bqcygyqrbH
  28. GZIIeGcWpmzeitWgSUNLMSIpdl/VoBSvZUMggdJyOHXayo/EhfFddGHdkfz0B0GW
  29. LzH8ow4JcYdhkTl4+xQstXJNVRJyw5ezFy35FHwNAoGAGZzjKP470R7lyS03r3wY
  30. Jelb5p8elM+XfemLO0i/HbY6QbuoZk9/GMac9tWz9jynJtC3smmn0KjXEaJzB2CZ
  31. VHWMewygFZo5mgnBS5XhPoldQjv310wnnw/Y/osXy/CL7KOK8Gt0lflqttNUOWvl
  32. +MLwO6+FnUXA2Gp42Lr/8SECgYANf2pEK2HewDHfmIwi6yp3pXPzAUmIlGanc1y6
  33. +lDxD/CYzTta+erdc/g9XFKWVsdciR9r+Pn/gW2bKve/3xer+qyBCDilfXZXRN4k
  34. jeuDhspQO0hUEg2b0AS2azQwlBiDQHX7tWg/CvBAbk5nBXpgJNf7aflfyDV/untF
  35. 4SlgTQKBgGmcyU02lyM6ogGbzWqSsHgR1ZhYyTV9DekQx9GysLG1wT2QzgjxOw4K
  36. 5PnVkOXr/ORqt+vJsYrtqBZQihmPPREKEwr2n8BRw0364z02wjvP04hDBHp4S5Ej
  37. PQeC5qErboVGMMpM2SamqGEfr+HJ/uRF6mEmm+xjI57aOvAwPW0B
  38. -----END RSA PRIVATE KEY-----"""
  39. PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
  40. MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA97wPWxpq5cClRu8Ssq60
  41. 9ZLfyx6E8ln/v/PdFZ7fxxmA4k+z1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqd
  42. d453d1eY95xYVbFrIHs7yJy8lcDR2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIb
  43. RjA2wmt2PVT26YbOX2qCMItV1+meo/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhh
  44. GY2b4PKuSTcsYjbg8adOGzFL9RXLI1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN
  45. 5ZEEz+sIdlMPCAACaZAY/t9Kd/LxHr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xl
  46. qQIDAQAB
  47. -----END PUBLIC KEY-----"""
  48. class SecretRoleTest(HttpStatusMixin, APITestCase):
  49. def setUp(self):
  50. user = User.objects.create(username='testuser', is_superuser=True)
  51. token = Token.objects.create(user=user)
  52. self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(token.key)}
  53. self.secretrole1 = SecretRole.objects.create(name='Test Secret Role 1', slug='test-secret-role-1')
  54. self.secretrole2 = SecretRole.objects.create(name='Test Secret Role 2', slug='test-secret-role-2')
  55. self.secretrole3 = SecretRole.objects.create(name='Test Secret Role 3', slug='test-secret-role-3')
  56. def test_get_secretrole(self):
  57. url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
  58. response = self.client.get(url, **self.header)
  59. self.assertEqual(response.data['name'], self.secretrole1.name)
  60. def test_list_secretroles(self):
  61. url = reverse('secrets-api:secretrole-list')
  62. response = self.client.get(url, **self.header)
  63. self.assertEqual(response.data['count'], 3)
  64. def test_create_secretrole(self):
  65. data = {
  66. 'name': 'Test Secret Role 4',
  67. 'slug': 'test-secret-role-4',
  68. }
  69. url = reverse('secrets-api:secretrole-list')
  70. response = self.client.post(url, data, format='json', **self.header)
  71. self.assertHttpStatus(response, status.HTTP_201_CREATED)
  72. self.assertEqual(SecretRole.objects.count(), 4)
  73. secretrole4 = SecretRole.objects.get(pk=response.data['id'])
  74. self.assertEqual(secretrole4.name, data['name'])
  75. self.assertEqual(secretrole4.slug, data['slug'])
  76. def test_create_secretrole_bulk(self):
  77. data = [
  78. {
  79. 'name': 'Test Secret Role 4',
  80. 'slug': 'test-secret-role-4',
  81. },
  82. {
  83. 'name': 'Test Secret Role 5',
  84. 'slug': 'test-secret-role-5',
  85. },
  86. {
  87. 'name': 'Test Secret Role 6',
  88. 'slug': 'test-secret-role-6',
  89. },
  90. ]
  91. url = reverse('secrets-api:secretrole-list')
  92. response = self.client.post(url, data, format='json', **self.header)
  93. self.assertHttpStatus(response, status.HTTP_201_CREATED)
  94. self.assertEqual(SecretRole.objects.count(), 6)
  95. self.assertEqual(response.data[0]['name'], data[0]['name'])
  96. self.assertEqual(response.data[1]['name'], data[1]['name'])
  97. self.assertEqual(response.data[2]['name'], data[2]['name'])
  98. def test_update_secretrole(self):
  99. data = {
  100. 'name': 'Test SecretRole X',
  101. 'slug': 'test-secretrole-x',
  102. }
  103. url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
  104. response = self.client.put(url, data, format='json', **self.header)
  105. self.assertHttpStatus(response, status.HTTP_200_OK)
  106. self.assertEqual(SecretRole.objects.count(), 3)
  107. secretrole1 = SecretRole.objects.get(pk=response.data['id'])
  108. self.assertEqual(secretrole1.name, data['name'])
  109. self.assertEqual(secretrole1.slug, data['slug'])
  110. def test_delete_secretrole(self):
  111. url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
  112. response = self.client.delete(url, **self.header)
  113. self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
  114. self.assertEqual(SecretRole.objects.count(), 2)
  115. class SecretTest(HttpStatusMixin, APITestCase):
  116. def setUp(self):
  117. user = User.objects.create(username='testuser', is_superuser=True)
  118. token = Token.objects.create(user=user)
  119. userkey = UserKey(user=user, public_key=PUBLIC_KEY)
  120. userkey.save()
  121. self.master_key = userkey.get_master_key(PRIVATE_KEY)
  122. session_key = SessionKey(userkey=userkey)
  123. session_key.save(self.master_key)
  124. self.header = {
  125. 'HTTP_AUTHORIZATION': 'Token {}'.format(token.key),
  126. 'HTTP_X_SESSION_KEY': base64.b64encode(session_key.key),
  127. }
  128. self.plaintext = {
  129. 'secret1': 'Secret #1 Plaintext',
  130. 'secret2': 'Secret #2 Plaintext',
  131. 'secret3': 'Secret #3 Plaintext',
  132. }
  133. site = Site.objects.create(name='Test Site 1', slug='test-site-1')
  134. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  135. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Test Device Type 1')
  136. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1')
  137. self.device = Device.objects.create(
  138. name='Test Device 1', site=site, device_type=devicetype, device_role=devicerole
  139. )
  140. self.secretrole1 = SecretRole.objects.create(name='Test Secret Role 1', slug='test-secret-role-1')
  141. self.secretrole2 = SecretRole.objects.create(name='Test Secret Role 2', slug='test-secret-role-2')
  142. self.secret1 = Secret(
  143. device=self.device, role=self.secretrole1, name='Test Secret 1', plaintext=self.plaintext['secret1']
  144. )
  145. self.secret1.encrypt(self.master_key)
  146. self.secret1.save()
  147. self.secret2 = Secret(
  148. device=self.device, role=self.secretrole1, name='Test Secret 2', plaintext=self.plaintext['secret2']
  149. )
  150. self.secret2.encrypt(self.master_key)
  151. self.secret2.save()
  152. self.secret3 = Secret(
  153. device=self.device, role=self.secretrole1, name='Test Secret 3', plaintext=self.plaintext['secret3']
  154. )
  155. self.secret3.encrypt(self.master_key)
  156. self.secret3.save()
  157. def test_get_secret(self):
  158. url = reverse('secrets-api:secret-detail', kwargs={'pk': self.secret1.pk})
  159. response = self.client.get(url, **self.header)
  160. self.assertEqual(response.data['plaintext'], self.plaintext['secret1'])
  161. def test_list_secrets(self):
  162. url = reverse('secrets-api:secret-list')
  163. response = self.client.get(url, **self.header)
  164. self.assertEqual(response.data['count'], 3)
  165. def test_create_secret(self):
  166. data = {
  167. 'device': self.device.pk,
  168. 'role': self.secretrole1.pk,
  169. 'name': 'Test Secret 4',
  170. 'plaintext': 'Secret #4 Plaintext',
  171. }
  172. url = reverse('secrets-api:secret-list')
  173. response = self.client.post(url, data, format='json', **self.header)
  174. self.assertHttpStatus(response, status.HTTP_201_CREATED)
  175. self.assertEqual(response.data['plaintext'], data['plaintext'])
  176. self.assertEqual(Secret.objects.count(), 4)
  177. secret4 = Secret.objects.get(pk=response.data['id'])
  178. secret4.decrypt(self.master_key)
  179. self.assertEqual(secret4.role_id, data['role'])
  180. self.assertEqual(secret4.plaintext, data['plaintext'])
  181. def test_create_secret_bulk(self):
  182. data = [
  183. {
  184. 'device': self.device.pk,
  185. 'role': self.secretrole1.pk,
  186. 'name': 'Test Secret 4',
  187. 'plaintext': 'Secret #4 Plaintext',
  188. },
  189. {
  190. 'device': self.device.pk,
  191. 'role': self.secretrole1.pk,
  192. 'name': 'Test Secret 5',
  193. 'plaintext': 'Secret #5 Plaintext',
  194. },
  195. {
  196. 'device': self.device.pk,
  197. 'role': self.secretrole1.pk,
  198. 'name': 'Test Secret 6',
  199. 'plaintext': 'Secret #6 Plaintext',
  200. },
  201. ]
  202. url = reverse('secrets-api:secret-list')
  203. response = self.client.post(url, data, format='json', **self.header)
  204. self.assertHttpStatus(response, status.HTTP_201_CREATED)
  205. self.assertEqual(Secret.objects.count(), 6)
  206. self.assertEqual(response.data[0]['plaintext'], data[0]['plaintext'])
  207. self.assertEqual(response.data[1]['plaintext'], data[1]['plaintext'])
  208. self.assertEqual(response.data[2]['plaintext'], data[2]['plaintext'])
  209. def test_update_secret(self):
  210. data = {
  211. 'device': self.device.pk,
  212. 'role': self.secretrole2.pk,
  213. 'plaintext': 'NewPlaintext',
  214. }
  215. url = reverse('secrets-api:secret-detail', kwargs={'pk': self.secret1.pk})
  216. response = self.client.put(url, data, format='json', **self.header)
  217. self.assertHttpStatus(response, status.HTTP_200_OK)
  218. self.assertEqual(response.data['plaintext'], data['plaintext'])
  219. self.assertEqual(Secret.objects.count(), 3)
  220. secret1 = Secret.objects.get(pk=response.data['id'])
  221. secret1.decrypt(self.master_key)
  222. self.assertEqual(secret1.role_id, data['role'])
  223. self.assertEqual(secret1.plaintext, data['plaintext'])
  224. def test_delete_secret(self):
  225. url = reverse('secrets-api:secret-detail', kwargs={'pk': self.secret1.pk})
  226. response = self.client.delete(url, **self.header)
  227. self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
  228. self.assertEqual(Secret.objects.count(), 2)
  229. class GetSessionKeyTest(HttpStatusMixin, APITestCase):
  230. def setUp(self):
  231. user = User.objects.create(username='testuser', is_superuser=True)
  232. token = Token.objects.create(user=user)
  233. userkey = UserKey(user=user, public_key=PUBLIC_KEY)
  234. userkey.save()
  235. master_key = userkey.get_master_key(PRIVATE_KEY)
  236. self.session_key = SessionKey(userkey=userkey)
  237. self.session_key.save(master_key)
  238. self.header = {
  239. 'HTTP_AUTHORIZATION': 'Token {}'.format(token.key),
  240. }
  241. def test_get_session_key(self):
  242. encoded_session_key = base64.b64encode(self.session_key.key).decode()
  243. url = reverse('secrets-api:get-session-key-list')
  244. data = {
  245. 'private_key': PRIVATE_KEY,
  246. }
  247. response = self.client.post(url, data, **self.header)
  248. self.assertHttpStatus(response, status.HTTP_200_OK)
  249. self.assertIsNotNone(response.data.get('session_key'))
  250. self.assertNotEqual(response.data.get('session_key'), encoded_session_key)
  251. def test_get_session_key_preserved(self):
  252. encoded_session_key = base64.b64encode(self.session_key.key).decode()
  253. url = reverse('secrets-api:get-session-key-list') + '?preserve_key=True'
  254. data = {
  255. 'private_key': PRIVATE_KEY,
  256. }
  257. response = self.client.post(url, data, **self.header)
  258. self.assertHttpStatus(response, status.HTTP_200_OK)
  259. self.assertEqual(response.data.get('session_key'), encoded_session_key)