]>
Commit | Line | Data |
---|---|---|
ad918272 BZ |
1 | import subprocess |
2 | import json | |
3 | import unittest | |
86b3e4e8 | 4 | import os |
ad918272 | 5 | |
541bb91b | 6 | from test_helper import ApiTestCase, is_auth, pdnsutil, unique_zone_name |
ad918272 BZ |
7 | |
8 | @unittest.skipIf(not is_auth(), "Not applicable") | |
9 | class Cryptokeys(ApiTestCase): | |
ad918272 | 10 | |
541bb91b CH |
11 | def setUp(self): |
12 | super(Cryptokeys, self).setUp() | |
86b3e4e8 | 13 | self.keyid = 0 |
541bb91b CH |
14 | self.zone = unique_zone_name() |
15 | self.zone_nodot = self.zone[:-1] | |
16 | payload = { | |
17 | 'name': self.zone, | |
18 | 'kind': 'Native', | |
19 | 'nameservers': ['ns1.example.com.', 'ns2.example.com.'] | |
20 | } | |
21 | r = self.session.post( | |
22 | self.url("/api/v1/servers/localhost/zones"), | |
23 | data=json.dumps(payload), | |
24 | headers={'content-type': 'application/json'}) | |
25 | self.assert_success_json(r) | |
4bfebc93 | 26 | self.assertEqual(r.status_code, 201) |
ad918272 BZ |
27 | |
28 | def tearDown(self): | |
541bb91b | 29 | super(Cryptokeys, self).tearDown() |
86b3e4e8 BZ |
30 | self.remove_zone_key(self.keyid) |
31 | ||
32 | # Adding a key to self.zone using the pdnsutil command | |
33918299 RG |
33 | def add_zone_key(self, status=['inactive']): |
34 | return pdnsutil("add-zone-key", self.zone_nodot, "ksk", *status) | |
ad918272 | 35 | |
86b3e4e8 BZ |
36 | # Removes a key from self.zone by id using the pdnsutil command |
37 | def remove_zone_key(self, key_id): | |
541bb91b | 38 | return pdnsutil("remove-zone-key", self.zone_nodot, str(key_id)) |
86b3e4e8 BZ |
39 | |
40 | # This method tests the DELETE api call. | |
41 | def test_delete(self): | |
42 | self.keyid = self.add_zone_key() | |
ad918272 BZ |
43 | |
44 | #checks the status code. I don't know how to test explicit that the backend fail removing a key. | |
86b3e4e8 | 45 | r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid)) |
4bfebc93 CH |
46 | self.assertEqual(r.status_code, 204) |
47 | self.assertEqual(r.content, b"") | |
ad918272 BZ |
48 | |
49 | # Check that the key is actually deleted | |
541bb91b CH |
50 | out = pdnsutil("list-keys", self.zone) |
51 | self.assertNotIn(self.zone, out) | |
ad918272 | 52 | |
77bfe8de PL |
53 | def test_get_wrong_zone(self): |
54 | self.keyid = self.add_zone_key() | |
55 | r = self.session.get(self.url("/api/v1/servers/localhost/zones/"+self.zone+"fail/cryptokeys/"+self.keyid)) | |
4bfebc93 | 56 | self.assertEqual(r.status_code, 404) |
77bfe8de | 57 | |
75191dc4 PL |
58 | def test_delete_wrong_id(self): |
59 | self.keyid = self.add_zone_key() | |
60 | r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/1234567")) | |
4bfebc93 | 61 | self.assertEqual(r.status_code, 404) |
75191dc4 | 62 | |
86b3e4e8 BZ |
63 | def test_delete_wrong_zone(self): |
64 | self.keyid = self.add_zone_key() | |
ad918272 | 65 | #checks for not covered zonename |
86b3e4e8 | 66 | r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"fail/cryptokeys/"+self.keyid)) |
4bfebc93 | 67 | self.assertEqual(r.status_code, 404) |
ad918272 | 68 | |
86b3e4e8 BZ |
69 | def test_delete_key_is_gone(self): |
70 | self.keyid = self.add_zone_key() | |
71 | self.remove_zone_key(self.keyid) | |
ad918272 | 72 | #checks for key is gone. Its ok even if no key had to be deleted. Or something went wrong with the backend. |
86b3e4e8 | 73 | r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid)) |
4bfebc93 | 74 | self.assertEqual(r.status_code, 404) |
ad918272 BZ |
75 | |
76 | # Prepares the json object for Post and sends it to the server | |
541bb91b CH |
77 | def add_key(self, content='', type='ksk', active='true', algo='', bits=None): |
78 | payload = { | |
79 | 'keytype': type, | |
80 | 'active': active, | |
81 | } | |
82 | if algo: | |
83 | payload['algorithm'] = algo | |
84 | if bits is not None: | |
ad918272 BZ |
85 | payload['bits'] = bits |
86 | if content != '': | |
87 | payload['content'] = content | |
541bb91b | 88 | print("create key with payload:", payload) |
ad918272 | 89 | r = self.session.post( |
86b3e4e8 | 90 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys"), |
ad918272 BZ |
91 | data=json.dumps(payload), |
92 | headers={'content-type': 'application/json'}) | |
ad918272 | 93 | |
86b3e4e8 | 94 | return r |
ad918272 | 95 | |
86b3e4e8 | 96 | # Test POST for a positive result and delete the added key |
541bb91b | 97 | def post_helper(self, content='', algo='', bits=None): |
ad918272 BZ |
98 | r = self.add_key(content=content, algo=algo, bits=bits) |
99 | self.assert_success_json(r) | |
4bfebc93 | 100 | self.assertEqual(r.status_code, 201) |
ad918272 BZ |
101 | response = r.json() |
102 | # Only a ksk added, so expected type is csk | |
4bfebc93 | 103 | self.assertEqual(response['keytype'], 'csk') |
86b3e4e8 | 104 | self.keyid = response['id'] |
ad918272 | 105 | # Check if the key is actually added |
541bb91b CH |
106 | out = pdnsutil("list-keys", self.zone_nodot) |
107 | self.assertIn(self.zone_nodot, out) | |
ad918272 | 108 | |
86b3e4e8 | 109 | # Test POST to add a key with default algorithm |
ad918272 | 110 | def test_post(self): |
ad918272 BZ |
111 | self.post_helper() |
112 | ||
86b3e4e8 BZ |
113 | # Test POST to add a key with specific algorithm number |
114 | def test_post_specific_number(self): | |
86783480 | 115 | self.post_helper(algo=10, bits=1024) |
ad918272 | 116 | |
86b3e4e8 BZ |
117 | # Test POST to add a key with specific name and bits |
118 | def test_post_specific_name_bits(self): | |
86783480 | 119 | self.post_helper(algo="rsasha256", bits=2048) |
ad918272 | 120 | |
86b3e4e8 BZ |
121 | # Test POST to add a key with specific name |
122 | def test_post_specific_name(self): | |
ad918272 BZ |
123 | self.post_helper(algo='ecdsa256') |
124 | ||
86b3e4e8 BZ |
125 | # Test POST to add a private key from external resource |
126 | def test_post_content(self): | |
ad918272 BZ |
127 | self.post_helper(content="Private-key-format: v1.2\n"+ |
128 | "Algorithm: 8 (RSASHA256)\n"+ | |
129 | "Modulus: 4GlYLGgDI7ohnP8SmEW8EBERbNRusDcg0VQda/EPVHU=\n"+ | |
130 | "PublicExponent: AQAB\n"+ | |
131 | "PrivateExponent: JBnuXF5zOtkjtSz3odV+Fk5UNUTTeCsiI16dkcM7TVU=\n"+ | |
132 | "Prime1: /w7TM4118RoSEvP8+dgnCw==\n"+ | |
133 | "Prime2: 4T2KhkYLa3w7rdK3Cb2ifw==\n"+ | |
134 | "Exponent1: 3aeKj9Ct4JuhfWsgPBhGxQ==\n"+ | |
135 | "Exponent2: tfh1OMPQKBdnU6iATjNR2w==\n"+ | |
136 | "Coefficient: eVrHe/kauqOewSKndIImrg==)\n") | |
137 | ||
86b3e4e8 | 138 | def test_post_wrong_key_format(self): |
ad918272 BZ |
139 | r = self.add_key(content="trollololoooolll") |
140 | self.assert_error_json(r) | |
4bfebc93 | 141 | self.assertEqual(r.status_code, 422) |
86b3e4e8 | 142 | self.assertIn("Key could not be parsed. Make sure your key format is correct.",r.json()['error']) |
ad918272 | 143 | |
86b3e4e8 | 144 | def test_post_wrong_keytype(self): |
ad918272 BZ |
145 | r = self.add_key(type='sdfdhhgj') |
146 | self.assert_error_json(r) | |
4bfebc93 | 147 | self.assertEqual(r.status_code, 422) |
ad918272 BZ |
148 | self.assertIn("Invalid keytype",r.json()['error']) |
149 | ||
86b3e4e8 BZ |
150 | def test_post_wrong_bits_format(self): |
151 | r = self.add_key(bits='sdfdhhgj') | |
152 | self.assert_error_json(r) | |
4bfebc93 | 153 | self.assertEqual(r.status_code, 422) |
86b3e4e8 BZ |
154 | self.assertIn("'bits' must be a positive integer value",r.json()['error']) |
155 | ||
156 | r = self.add_key(bits='5.5') | |
157 | self.assert_error_json(r) | |
4bfebc93 | 158 | self.assertEqual(r.status_code, 422) |
86b3e4e8 BZ |
159 | self.assertIn("'bits' must be a positive integer value",r.json()['error']) |
160 | ||
161 | r = self.add_key(bits='-6') | |
162 | self.assert_error_json(r) | |
4bfebc93 | 163 | self.assertEqual(r.status_code, 422) |
86b3e4e8 BZ |
164 | self.assertIn("'bits' must be a positive integer value",r.json()['error']) |
165 | ||
166 | def test_post_unsupported_algorithm(self): | |
ad918272 BZ |
167 | r = self.add_key(algo='lkjhgf') |
168 | self.assert_error_json(r) | |
4bfebc93 | 169 | self.assertEqual(r.status_code, 422) |
ad918272 BZ |
170 | self.assertIn("Unknown algorithm:",r.json()['error']) |
171 | ||
86b3e4e8 | 172 | def test_post_forgot_bits(self): |
ad918272 BZ |
173 | r = self.add_key(algo="rsasha256") |
174 | self.assert_error_json(r) | |
4bfebc93 | 175 | self.assertEqual(r.status_code, 422) |
ad918272 BZ |
176 | self.assertIn("key requires the size (in bits) to be passed", r.json()['error']) |
177 | ||
86b3e4e8 | 178 | def test_post_wrong_bit_size(self): |
ad918272 BZ |
179 | r = self.add_key(algo=10, bits=30) |
180 | self.assert_error_json(r) | |
4bfebc93 | 181 | self.assertEqual(r.status_code,422) |
86b3e4e8 | 182 | self.assertIn("The algorithm does not support the given bit size.", r.json()['error']) |
ad918272 | 183 | |
86b3e4e8 | 184 | def test_post_can_not_guess_key_size(self): |
9d3727e0 | 185 | r = self.add_key(algo=17) |
ad918272 | 186 | self.assert_error_json(r) |
4bfebc93 | 187 | self.assertEqual(r.status_code,422) |
86b3e4e8 | 188 | self.assertIn("Can not guess key size for algorithm", r.json()['error']) |
ad918272 | 189 | |
86b3e4e8 BZ |
190 | def test_put_activate_key(self): |
191 | self.keyid = self.add_zone_key() | |
ad918272 | 192 | |
ad918272 | 193 | payload = { |
33918299 RG |
194 | 'active': True, |
195 | 'published': True, | |
ad918272 | 196 | } |
86b3e4e8 BZ |
197 | r = self.session.put( |
198 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
ad918272 BZ |
199 | data=json.dumps(payload), |
200 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
201 | self.assertEqual(r.status_code, 204) |
202 | self.assertEqual(r.content, b"") | |
ad918272 BZ |
203 | |
204 | # check if key is activated | |
541bb91b CH |
205 | out = pdnsutil("show-zone", self.zone_nodot) |
206 | self.assertIn("Active", out) | |
ad918272 | 207 | |
86b3e4e8 | 208 | def test_put_deactivate_key(self): |
33918299 | 209 | self.keyid = self.add_zone_key(status=['active']) |
ad918272 BZ |
210 | # deactivate key |
211 | payload2 = { | |
33918299 RG |
212 | 'active': False, |
213 | 'published': True, | |
ad918272 | 214 | } |
86b3e4e8 BZ |
215 | |
216 | r = self.session.put( | |
217 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
ad918272 BZ |
218 | data=json.dumps(payload2), |
219 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
220 | self.assertEqual(r.status_code, 204) |
221 | self.assertEqual(r.content, b"") | |
ad918272 BZ |
222 | |
223 | # check if key is deactivated | |
541bb91b CH |
224 | out = pdnsutil("show-zone", self.zone_nodot) |
225 | self.assertIn("Inactive", out) | |
ad918272 | 226 | |
86b3e4e8 BZ |
227 | def test_put_deactivate_inactive_key(self): |
228 | self.keyid = self.add_zone_key() | |
ad918272 BZ |
229 | |
230 | # deactivate key | |
231 | payload = { | |
33918299 RG |
232 | 'active': False, |
233 | 'published': True, | |
ad918272 | 234 | } |
86b3e4e8 BZ |
235 | |
236 | r = self.session.put( | |
237 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
ad918272 BZ |
238 | data=json.dumps(payload), |
239 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
240 | self.assertEqual(r.status_code, 204) |
241 | self.assertEqual(r.content, b"") | |
ad918272 BZ |
242 | |
243 | # check if key is still deactivated | |
541bb91b CH |
244 | out = pdnsutil("show-zone", self.zone_nodot) |
245 | self.assertIn("Inactive", out) | |
ad918272 | 246 | |
86b3e4e8 | 247 | def test_put_activate_active_key(self): |
33918299 | 248 | self.keyid = self.add_zone_key(status=['active']) |
86b3e4e8 | 249 | |
ad918272 BZ |
250 | # activate key |
251 | payload2 = { | |
33918299 RG |
252 | 'active': True, |
253 | 'published': True, | |
ad918272 | 254 | } |
86b3e4e8 BZ |
255 | r = self.session.put( |
256 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
ad918272 BZ |
257 | data=json.dumps(payload2), |
258 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
259 | self.assertEqual(r.status_code, 204) |
260 | self.assertEqual(r.content, b"") | |
ad918272 BZ |
261 | |
262 | # check if key is activated | |
541bb91b CH |
263 | out = pdnsutil("show-zone", self.zone_nodot) |
264 | self.assertIn("Active", out) | |
33918299 RG |
265 | |
266 | def test_put_unpublish_key(self): | |
267 | self.keyid = self.add_zone_key(status=['active']) | |
268 | ||
269 | payload = { | |
270 | 'active': True, | |
271 | 'published': False, | |
272 | } | |
273 | r = self.session.put( | |
274 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
275 | data=json.dumps(payload), | |
276 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
277 | self.assertEqual(r.status_code, 204) |
278 | self.assertEqual(r.content, b"") | |
33918299 RG |
279 | |
280 | # check if key is activated | |
281 | out = pdnsutil("show-zone", self.zone_nodot) | |
282 | self.assertIn("Unpublished", out) | |
283 | ||
284 | def test_put_publish_key(self): | |
285 | self.keyid = self.add_zone_key(status=['active', 'unpublished']) | |
286 | # deactivate key | |
287 | payload2 = { | |
288 | 'active': True, | |
289 | 'published': True, | |
290 | } | |
291 | ||
292 | r = self.session.put( | |
293 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
294 | data=json.dumps(payload2), | |
295 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
296 | self.assertEqual(r.status_code, 204) |
297 | self.assertEqual(r.content, b"") | |
33918299 RG |
298 | |
299 | # check if key is deactivated | |
300 | out = pdnsutil("show-zone", self.zone_nodot) | |
301 | self.assertIn("Published", out) | |
302 | ||
303 | def test_put_publish_published_key(self): | |
304 | self.keyid = self.add_zone_key(status=['active']) | |
305 | ||
306 | # deactivate key | |
307 | payload = { | |
308 | 'active': True, | |
309 | 'published': True, | |
310 | } | |
311 | ||
312 | r = self.session.put( | |
313 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
314 | data=json.dumps(payload), | |
315 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
316 | self.assertEqual(r.status_code, 204) |
317 | self.assertEqual(r.content, b"") | |
33918299 RG |
318 | |
319 | # check if key is still deactivated | |
320 | out = pdnsutil("show-zone", self.zone_nodot) | |
321 | self.assertIn("Published", out) | |
322 | ||
323 | def test_put_unpublish_unpublished_key(self): | |
324 | self.keyid = self.add_zone_key(status=['active', 'unpublished']) | |
325 | ||
326 | # activate key | |
327 | payload2 = { | |
328 | 'active': True, | |
329 | 'published': False, | |
330 | } | |
331 | r = self.session.put( | |
332 | self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid), | |
333 | data=json.dumps(payload2), | |
334 | headers={'content-type': 'application/json'}) | |
4bfebc93 CH |
335 | self.assertEqual(r.status_code, 204) |
336 | self.assertEqual(r.content, b"") | |
33918299 RG |
337 | |
338 | # check if key is activated | |
339 | out = pdnsutil("show-zone", self.zone_nodot) | |
340 | self.assertIn("Unpublished", out) |