test_api.py 13 KB

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