Browse Source

Wrote tests for secrets API

Jeremy Stretch 8 years ago
parent
commit
130ff27f26
2 changed files with 239 additions and 0 deletions
  1. 12 0
      netbox/secrets/api/serializers.py
  2. 227 0
      netbox/secrets/tests/test_api.py

+ 12 - 0
netbox/secrets/api/serializers.py

@@ -1,4 +1,5 @@
 from rest_framework import serializers
+from rest_framework.validators import UniqueTogetherValidator
 
 from dcim.api.serializers import NestedDeviceSerializer
 from secrets.models import Secret, SecretRole
@@ -42,3 +43,14 @@ class WritableSecretSerializer(serializers.ModelSerializer):
     class Meta:
         model = Secret
         fields = ['id', 'device', 'role', 'name', 'plaintext']
+        validators = []
+
+    def validate(self, data):
+
+        # Validate uniqueness of name if one has been provided.
+        if data.get('name', None):
+            validator = UniqueTogetherValidator(queryset=Secret.objects.all(), fields=('device', 'role', 'name'))
+            validator.set_context(self)
+            validator(data)
+
+        return data

+ 227 - 0
netbox/secrets/tests/test_api.py

@@ -0,0 +1,227 @@
+import base64
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+from django.contrib.auth.models import User
+from django.urls import reverse
+
+from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
+from secrets.models import Secret, SecretRole, SessionKey, UserKey
+from users.models import Token
+
+
+# Dummy RSA key pair for testing use only
+PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA97wPWxpq5cClRu8Ssq609ZLfyx6E8ln/v/PdFZ7fxxmA4k+z
+1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqdd453d1eY95xYVbFrIHs7yJy8lcDR
+2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIbRjA2wmt2PVT26YbOX2qCMItV1+me
+o/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhhGY2b4PKuSTcsYjbg8adOGzFL9RXL
+I1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN5ZEEz+sIdlMPCAACaZAY/t9Kd/Lx
+Hr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xlqQIDAQABAoIBAQC4pDQVxNTTtQf6
+nImlH83EEto1++M+9pFFsi6fxLApJvsGsjzomke1Dy7uN93qVGk8rq3enzSYU58f
+sSs8BVKkH00vZ9ydAKxeAkREC1V9qkRsoTBHUY47sJcDkyZyssxfLNm7w0Q70h7a
+mLVEJBqr75eAxLN19vOpDk6Wkz3Bi0Dj27HLeme3hH5jLVQIIswWZnUDP3r/sdM/
+WA2GjoycPbug0r1FVZnxkFCrQ5yMfH3VzKBelj7356+5sc/TUXedDFN/DV2b90Ll
++au7EEXecFYZwmX3SX2hpe6IWEpUW3B0fvm+Ipm8h7x68i7J0oi9EUXW2+UQYfOx
+dDLxTLvhAoGBAPtJJox4XcpzipSAzKxyV8K9ikUZCG2wJU7VHyZ5zpSXwl/husls
+brAzHQcnWayhxxuWeiQ6pLnRFPFXjlOH2FZqHXSLnfpDaymEksDPvo9GqRE3Q+F+
+lDRn72H1NLIj3Y3t5SwWRB34Dhy+gd5Ht9L3dCTH8cYvJGnmS4sH/z0NAoGBAPxh
+2rhS1B0S9mqqvpduUPxqUIWaztXaHC6ZikloOFcgVMdh9MRrpa2sa+bqcygyqrbH
+GZIIeGcWpmzeitWgSUNLMSIpdl/VoBSvZUMggdJyOHXayo/EhfFddGHdkfz0B0GW
+LzH8ow4JcYdhkTl4+xQstXJNVRJyw5ezFy35FHwNAoGAGZzjKP470R7lyS03r3wY
+Jelb5p8elM+XfemLO0i/HbY6QbuoZk9/GMac9tWz9jynJtC3smmn0KjXEaJzB2CZ
+VHWMewygFZo5mgnBS5XhPoldQjv310wnnw/Y/osXy/CL7KOK8Gt0lflqttNUOWvl
++MLwO6+FnUXA2Gp42Lr/8SECgYANf2pEK2HewDHfmIwi6yp3pXPzAUmIlGanc1y6
++lDxD/CYzTta+erdc/g9XFKWVsdciR9r+Pn/gW2bKve/3xer+qyBCDilfXZXRN4k
+jeuDhspQO0hUEg2b0AS2azQwlBiDQHX7tWg/CvBAbk5nBXpgJNf7aflfyDV/untF
+4SlgTQKBgGmcyU02lyM6ogGbzWqSsHgR1ZhYyTV9DekQx9GysLG1wT2QzgjxOw4K
+5PnVkOXr/ORqt+vJsYrtqBZQihmPPREKEwr2n8BRw0364z02wjvP04hDBHp4S5Ej
+PQeC5qErboVGMMpM2SamqGEfr+HJ/uRF6mEmm+xjI57aOvAwPW0B
+-----END RSA PRIVATE KEY-----"""
+
+PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA97wPWxpq5cClRu8Ssq60
+9ZLfyx6E8ln/v/PdFZ7fxxmA4k+z1Q/Rn9/897PWy+1x2ZKlHjmaw1z7dS3PlGqd
+d453d1eY95xYVbFrIHs7yJy8lcDR2criwGEI68VP1FwcOkkwhicjtQZQS5fkkBIb
+RjA2wmt2PVT26YbOX2qCMItV1+meo/Ogh+uI1oNePJ8VYuGXbGNggf1qMY8fGhhh
+GY2b4PKuSTcsYjbg8adOGzFL9RXLI1X4PHNCzD/Y1vdM3jJXv+luk3TU+JIbzJeN
+5ZEEz+sIdlMPCAACaZAY/t9Kd/LxHr0o4K/6gqkZIukxFCK6sN53gibAXfaKc4xl
+qQIDAQAB
+-----END PUBLIC KEY-----"""
+
+
+class SecretRoleTest(APITestCase):
+
+    def setUp(self):
+
+        user = User.objects.create(username='testuser', is_superuser=True)
+        token = Token.objects.create(user=user)
+        self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(token.key)}
+
+        self.secretrole1 = SecretRole.objects.create(name='Test Secret Role 1', slug='test-secret-role-1')
+        self.secretrole2 = SecretRole.objects.create(name='Test Secret Role 2', slug='test-secret-role-2')
+        self.secretrole3 = SecretRole.objects.create(name='Test Secret Role 3', slug='test-secret-role-3')
+
+    def test_get_secretrole(self):
+
+        url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
+        response = self.client.get(url, **self.header)
+
+        self.assertEqual(response.data['name'], self.secretrole1.name)
+
+    def test_list_secretroles(self):
+
+        url = reverse('secrets-api:secretrole-list')
+        response = self.client.get(url, **self.header)
+
+        self.assertEqual(response.data['count'], 3)
+
+    def test_create_secretrole(self):
+
+        data = {
+            'name': 'Test SecretRole 4',
+            'slug': 'test-secretrole-4',
+        }
+
+        url = reverse('secrets-api:secretrole-list')
+        response = self.client.post(url, data, **self.header)
+
+        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        self.assertEqual(SecretRole.objects.count(), 4)
+        secretrole4 = SecretRole.objects.get(pk=response.data['id'])
+        self.assertEqual(secretrole4.name, data['name'])
+        self.assertEqual(secretrole4.slug, data['slug'])
+
+    def test_update_secretrole(self):
+
+        data = {
+            'name': 'Test SecretRole X',
+            'slug': 'test-secretrole-x',
+        }
+
+        url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
+        response = self.client.put(url, data, **self.header)
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(SecretRole.objects.count(), 3)
+        secretrole1 = SecretRole.objects.get(pk=response.data['id'])
+        self.assertEqual(secretrole1.name, data['name'])
+        self.assertEqual(secretrole1.slug, data['slug'])
+
+    def test_delete_secretrole(self):
+
+        url = reverse('secrets-api:secretrole-detail', kwargs={'pk': self.secretrole1.pk})
+        response = self.client.delete(url, **self.header)
+
+        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+        self.assertEqual(SecretRole.objects.count(), 2)
+
+
+class SecretTest(APITestCase):
+
+    def setUp(self):
+
+        user = User.objects.create(username='testuser', is_superuser=True)
+        token = Token.objects.create(user=user)
+
+        userkey = UserKey(user=user, public_key=PUBLIC_KEY)
+        userkey.save()
+        self.master_key = userkey.get_master_key(PRIVATE_KEY)
+        session_key = SessionKey(userkey=userkey)
+        session_key.save(self.master_key)
+
+        self.header = {
+            'HTTP_AUTHORIZATION': 'Token {}'.format(token.key),
+            'HTTP_X_SESSION_KEY': base64.b64encode(session_key.key),
+        }
+
+        self.plaintext = {
+            'secret1': 'Secret#1Plaintext',
+            'secret2': 'Secret#2Plaintext',
+            'secret3': 'Secret#3Plaintext',
+        }
+
+        site = Site.objects.create(name='Test Site 1', slug='test-site-1')
+        manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
+        devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Test Device Type 1')
+        devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1')
+        self.device = Device.objects.create(
+            name='Test Device 1', site=site, device_type=devicetype, device_role=devicerole
+        )
+        self.secretrole1 = SecretRole.objects.create(name='Test Secret Role 1', slug='test-secret-role-1')
+        self.secretrole2 = SecretRole.objects.create(name='Test Secret Role 2', slug='test-secret-role-2')
+        self.secret1 = Secret(
+            device=self.device, role=self.secretrole1, name='Test Secret 1', plaintext=self.plaintext['secret1']
+        )
+        self.secret1.encrypt(self.master_key)
+        self.secret1.save()
+        self.secret2 = Secret(
+            device=self.device, role=self.secretrole1, name='Test Secret 2', plaintext=self.plaintext['secret2']
+        )
+        self.secret2.encrypt(self.master_key)
+        self.secret2.save()
+        self.secret3 = Secret(
+            device=self.device, role=self.secretrole1, name='Test Secret 3', plaintext=self.plaintext['secret3']
+        )
+        self.secret3.encrypt(self.master_key)
+        self.secret3.save()
+
+    def test_get_secret(self):
+
+        url = reverse('secrets-api:secret-detail', kwargs={'pk': self.secret1.pk})
+        response = self.client.get(url, **self.header)
+
+        self.assertEqual(response.data['plaintext'], self.plaintext['secret1'])
+
+    def test_list_secrets(self):
+
+        url = reverse('secrets-api:secret-list')
+        response = self.client.get(url, **self.header)
+
+        self.assertEqual(response.data['count'], 3)
+
+    def test_create_secret(self):
+
+        data = {
+            'device': self.device.pk,
+            'role': self.secretrole1.pk,
+            'plaintext': 'Secret#4Plaintext',
+        }
+
+        url = reverse('secrets-api:secret-list')
+        response = self.client.post(url, data, **self.header)
+
+        self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)
+        self.assertEqual(response.data['plaintext'], data['plaintext'])
+        self.assertEqual(Secret.objects.count(), 4)
+        secret4 = Secret.objects.get(pk=response.data['id'])
+        secret4.decrypt(self.master_key)
+        self.assertEqual(secret4.role_id, data['role'])
+        self.assertEqual(secret4.plaintext, data['plaintext'])
+
+    def test_update_secret(self):
+
+        data = {
+            'device': self.device.pk,
+            'role': self.secretrole2.pk,
+            'plaintext': 'NewPlaintext',
+        }
+
+        url = reverse('secrets-api:secret-detail', kwargs={'pk': self.secret1.pk})
+        response = self.client.put(url, data, **self.header)
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
+        self.assertEqual(response.data['plaintext'], data['plaintext'])
+        self.assertEqual(Secret.objects.count(), 3)
+        secret1 = Secret.objects.get(pk=response.data['id'])
+        secret1.decrypt(self.master_key)
+        self.assertEqual(secret1.role_id, data['role'])
+        self.assertEqual(secret1.plaintext, data['plaintext'])
+
+    def test_delete_secret(self):
+
+        url = reverse('secrets-api:secret-detail', kwargs={'pk': self.secret1.pk})
+        response = self.client.delete(url, **self.header)
+
+        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+        self.assertEqual(Secret.objects.count(), 2)