|
| 1 | +from django.contrib.auth.models import User |
| 2 | +from django.core.cache import cache |
| 3 | +from django.test import override_settings |
| 4 | +from rest_framework.test import APITestCase |
| 5 | +from rest_framework.authtoken.models import Token |
| 6 | + |
| 7 | +from api.models import App, Certificate, Domain |
| 8 | +from api.tests import TEST_ROOT |
| 9 | + |
| 10 | + |
| 11 | +@override_settings(DEIS_KUBERNETES_DEPLOYMENTS='1') |
| 12 | +class CertificateUseCase1Test(APITestCase): |
| 13 | + |
| 14 | + """ |
| 15 | + Tests creation of domain SSL certificate and attach the |
| 16 | + certificate to a domain and then detach |
| 17 | + """ |
| 18 | + |
| 19 | + fixtures = ['tests.json'] |
| 20 | + |
| 21 | + def setUp(self): |
| 22 | + self.user = User.objects.get(username='autotest') |
| 23 | + self.token = Token.objects.get(user=self.user).key |
| 24 | + self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) |
| 25 | + |
| 26 | + self.url = '/v2/certs' |
| 27 | + self.app = App.objects.create(owner=self.user, id='test-app-use-case-1') |
| 28 | + self.domain = Domain.objects.create(owner=self.user, app=self.app, domain='foo.com') |
| 29 | + self.name = 'foo-com' # certificate name |
| 30 | + |
| 31 | + with open('{}/certs/{}.key'.format(TEST_ROOT, self.domain)) as f: |
| 32 | + self.key = f.read() |
| 33 | + |
| 34 | + with open('{}/certs/{}.cert'.format(TEST_ROOT, self.domain)) as f: |
| 35 | + self.cert = f.read() |
| 36 | + |
| 37 | + def tearDown(self): |
| 38 | + # make sure every test has a clean slate for k8s mocking |
| 39 | + cache.clear() |
| 40 | + |
| 41 | + def test_create_certificate_with_domain(self): |
| 42 | + """Tests creating a certificate.""" |
| 43 | + response = self.client.post( |
| 44 | + self.url, |
| 45 | + { |
| 46 | + 'name': self.name, |
| 47 | + 'certificate': self.cert, |
| 48 | + 'key': self.key |
| 49 | + } |
| 50 | + ) |
| 51 | + self.assertEqual(response.status_code, 201, response.data) |
| 52 | + |
| 53 | + def test_create_certificate_with_different_common_name(self): |
| 54 | + """ |
| 55 | + Make sure common_name is read-only |
| 56 | + """ |
| 57 | + response = self.client.post( |
| 58 | + self.url, |
| 59 | + { |
| 60 | + 'name': self.name, |
| 61 | + 'certificate': self.cert, |
| 62 | + 'key': self.key, |
| 63 | + 'common_name': 'foo.example.com' |
| 64 | + } |
| 65 | + ) |
| 66 | + self.assertEqual(response.status_code, 201, response.data) |
| 67 | + self.assertEqual(response.data['common_name'], 'foo.com') |
| 68 | + |
| 69 | + def test_get_certificate_screens_data(self): |
| 70 | + """ |
| 71 | + When a user retrieves a certificate make sure proper data is returned |
| 72 | + """ |
| 73 | + # Create certificate |
| 74 | + response = self.client.post( |
| 75 | + self.url, |
| 76 | + { |
| 77 | + 'name': self.name, |
| 78 | + 'certificate': self.cert, |
| 79 | + 'key': self.key |
| 80 | + } |
| 81 | + ) |
| 82 | + self.assertEqual(response.status_code, 201, response.data) |
| 83 | + |
| 84 | + # Attach to domain that does not exist |
| 85 | + response = self.client.post( |
| 86 | + '{}/{}/domain/'.format(self.url, self.name), |
| 87 | + {'domain': 'random.com'} |
| 88 | + ) |
| 89 | + self.assertEqual(response.status_code, 404) |
| 90 | + |
| 91 | + # Attach domain to certificate |
| 92 | + response = self.client.post( |
| 93 | + '{}/{}/domain/'.format(self.url, self.name), |
| 94 | + {'domain': str(self.domain)} |
| 95 | + ) |
| 96 | + self.assertEqual(response.status_code, 201, response.data) |
| 97 | + |
| 98 | + # Assert data |
| 99 | + response = self.client.get('{}/{}'.format(self.url, self.name)) |
| 100 | + self.assertEqual(response.status_code, 200, response.data) |
| 101 | + |
| 102 | + expected = { |
| 103 | + 'name': self.name, |
| 104 | + 'common_name': str(self.domain), |
| 105 | + 'expires': '2017-01-14T23:55:59Z', |
| 106 | + 'fingerprint': 'AC:82:58:80:EA:C4:B9:75:C1:1C:52:48:40:28:15:1D:47:AC:ED:88:4B:D4:72:95:B2:C0:A0:DF:4A:A7:60:B6', # noqa |
| 107 | + 'san': [], |
| 108 | + 'domains': ['foo.com'] |
| 109 | + } |
| 110 | + for key, value in list(expected.items()): |
| 111 | + self.assertEqual(response.data[key], value, key) |
| 112 | + |
| 113 | + # detach domain from a certificate |
| 114 | + response = self.client.delete( |
| 115 | + '{}/{}/domain/{}'.format(self.url, self.name, self.domain) |
| 116 | + ) |
| 117 | + self.assertEqual(response.status_code, 204, response.data) |
| 118 | + |
| 119 | + # detach a domain that does not exist from a certificate |
| 120 | + response = self.client.delete( |
| 121 | + '{}/{}/domain/{}'.format(self.url, self.name, 'i-am-fake.com') |
| 122 | + ) |
| 123 | + self.assertEqual(response.status_code, 404) |
| 124 | + |
| 125 | + # Assert data |
| 126 | + response = self.client.get('{}/{}'.format(self.url, self.name)) |
| 127 | + self.assertEqual(response.status_code, 200, response.data) |
| 128 | + self.assertEqual(response.data['domains'], []) |
| 129 | + |
| 130 | + def test_certficate_denied_requests(self): |
| 131 | + """Disallow put/patch requests""" |
| 132 | + response = self.client.put(self.url) |
| 133 | + self.assertEqual(response.status_code, 405, response.content) |
| 134 | + response = self.client.patch(self.url) |
| 135 | + self.assertEqual(response.status_code, 405, response.content) |
| 136 | + |
| 137 | + def test_delete_certificate(self): |
| 138 | + """Destroying a certificate should generate a 204 response""" |
| 139 | + Certificate.objects.create( |
| 140 | + owner=self.user, |
| 141 | + name=self.name, |
| 142 | + certificate=self.cert |
| 143 | + ) |
| 144 | + |
| 145 | + url = '/v2/certs/{}'.format(self.name) |
| 146 | + response = self.client.delete(url) |
| 147 | + self.assertEqual(response.status_code, 204, response.data) |
| 148 | + |
| 149 | + def test_delete_certificate_with_attached_domain(self): |
| 150 | + """ |
| 151 | + Destroy a certificate with attached domain. |
| 152 | + Domain should not have assigned cert anymore |
| 153 | + """ |
| 154 | + # Create certificate |
| 155 | + response = self.client.post( |
| 156 | + self.url, |
| 157 | + { |
| 158 | + 'name': self.name, |
| 159 | + 'certificate': self.cert, |
| 160 | + 'key': self.key |
| 161 | + } |
| 162 | + ) |
| 163 | + self.assertEqual(response.status_code, 201, response.data) |
| 164 | + |
| 165 | + # Attach domain to certificate |
| 166 | + response = self.client.post( |
| 167 | + '{}/{}/domain/'.format(self.url, self.name), |
| 168 | + {'domain': str(self.domain)} |
| 169 | + ) |
| 170 | + self.assertEqual(response.status_code, 201, response.data) |
| 171 | + |
| 172 | + # Assert data from cert side |
| 173 | + response = self.client.get('{}/{}'.format(self.url, self.name)) |
| 174 | + self.assertEqual(response.status_code, 200, response.data) |
| 175 | + self.assertEqual(response.data['domains'], [str(self.domain)]) |
| 176 | + |
| 177 | + # Assert data from domain side |
| 178 | + domain = Domain.objects.get(id=self.domain.id) |
| 179 | + self.assertEqual(domain.certificate.name, self.name) |
| 180 | + |
| 181 | + # Delete certificate |
| 182 | + url = '/v2/certs/{}'.format(self.name) |
| 183 | + response = self.client.delete(url) |
| 184 | + self.assertEqual(response.status_code, 204, response.data) |
| 185 | + |
| 186 | + # verify certificate is not attached to domain anymore |
| 187 | + domain = Domain.objects.get(id=self.domain.id) |
| 188 | + self.assertEqual(domain.certificate, None) |
0 commit comments