]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Implements API tests for cryptokeys
authorBenjamin Zengin <b.zengin@yahoo.de>
Tue, 5 Jul 2016 10:04:33 +0000 (12:04 +0200)
committerBenjamin Zengin <b.zengin@yahoo.de>
Tue, 6 Sep 2016 09:57:29 +0000 (11:57 +0200)
- PUT
- POST
- DELETE

regression-tests.api/test_cryptokeys.py [new file with mode: 0644]
regression-tests.api/test_helper.py

diff --git a/regression-tests.api/test_cryptokeys.py b/regression-tests.api/test_cryptokeys.py
new file mode 100644 (file)
index 0000000..cec5e38
--- /dev/null
@@ -0,0 +1,269 @@
+import subprocess
+import json
+import unittest
+
+from test_helper import ApiTestCase, is_auth
+
+@unittest.skipIf(not is_auth(), "Not applicable")
+class Cryptokeys(ApiTestCase):
+    zone = "cryptokeyzone"
+    def setUp(self):
+        super(Cryptokeys, self).setUp()
+        try:
+            subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "create-zone", Cryptokeys.zone])
+        except subprocess.CalledProcessError as e:
+            self.fail("Couldn't create zone: "+e.output)
+
+
+    def tearDown(self):
+        super(Cryptokeys,self).tearDown()
+        try:
+            subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "delete-zone", Cryptokeys.zone])
+        except subprocess.CalledProcessError as e:
+            self.fail("Couldn't delete zone: "+e.output)
+
+
+    # This methode test the DELETE api call. Sometimes 200 or 422 are valid return codes,
+    # because it "could" happen that the backend crashes during the test or the remove function returns false.
+    # In this case 422 is correct. I don't know how to force false backend behavior. So i assume that the backend
+    # works correct.
+    def test_delete(self):
+        try:
+            keyid = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "add-zone-key", Cryptokeys.zone, "ksk"])
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil add-zone-key failed: "+e.output)
+
+        #checks the status code. I don't know how to test explicit that the backend fail removing a key.
+        r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid))
+        self.assertTrue(r.status_code == 200 or r.status_code == 422)
+
+        # Check that the key is actually deleted
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "list-keys", Cryptokeys.zone])
+            self.assertFalse(Cryptokeys.zone in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil list-keys failed: " + e.output)
+
+        #checks for not covered zonename
+        r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"fail/cryptokeys/"+keyid))
+        self.assertEquals(r.status_code, 400)
+
+        #checks for key is gone. Its ok even if no key had to be deleted. Or something went wrong with the backend.
+        r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid))
+        self.assertTrue(r.status_code == 200 or r.status_code == 422)
+
+    # Prepares the json object for Post and sends it to the server
+    def add_key(self, content='', type='ksk', active='true' , algo='', bits=0):
+        if algo == '':
+            payload = {
+                'keytype': type,
+                'active' : active
+            }
+        else:
+            payload = {
+                'keytype': type,
+                'active' : active,
+                'algo' : algo
+            }
+        if bits > 0:
+            payload['bits'] = bits
+        if content != '':
+            payload['content'] = content
+        r = self.session.post(
+            self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys"),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+        return r
+
+    # Removes a key by id using the pdnsutil command
+    def remove_key(self, key_id):
+        try:
+            subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "remove-zone-key", Cryptokeys.zone, str(key_id)])
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil remove-zone-key failed: "+e.output)
+
+    # Tests POST for a positiv result and deletes the added key
+    def post_helper(self,content='', algo='', bits=0):
+        r = self.add_key(content=content, algo=algo, bits=bits)
+        self.assert_success_json(r)
+        self.assertEquals(r.status_code, 201)
+        response = r.json()
+        # Only a ksk added, so expected type is csk
+        self.assertEquals(response['keytype'], 'csk')
+        key_id = response['id']
+        # Check if the key is actually added
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "list-keys", Cryptokeys.zone])
+            self.assertTrue(Cryptokeys.zone in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil list-keys failed: " + e.output)
+
+        # Remove it for further testing
+        self.remove_key(key_id)
+
+    def test_post(self):
+        # Test add a key with default algorithm
+        self.post_helper()
+
+        # Test add a key with specific number
+        self.post_helper(algo=10, bits=512)
+
+        # Test add a key with specific name and bits
+        self.post_helper(algo="rsasha256", bits=256)
+
+        # Test add a key with specific name
+        self.post_helper(algo='ecdsa256')
+
+        # Test add a private key from extern resource
+        self.post_helper(content="Private-key-format: v1.2\n"+
+                                 "Algorithm: 8 (RSASHA256)\n"+
+                                 "Modulus: 4GlYLGgDI7ohnP8SmEW8EBERbNRusDcg0VQda/EPVHU=\n"+
+                                 "PublicExponent: AQAB\n"+
+                                 "PrivateExponent: JBnuXF5zOtkjtSz3odV+Fk5UNUTTeCsiI16dkcM7TVU=\n"+
+                                 "Prime1: /w7TM4118RoSEvP8+dgnCw==\n"+
+                                 "Prime2: 4T2KhkYLa3w7rdK3Cb2ifw==\n"+
+                                 "Exponent1: 3aeKj9Ct4JuhfWsgPBhGxQ==\n"+
+                                 "Exponent2: tfh1OMPQKBdnU6iATjNR2w==\n"+
+                                 "Coefficient: eVrHe/kauqOewSKndIImrg==)\n")
+
+        # Test wrong key format
+        r = self.add_key(content="trollololoooolll")
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("Wrong key format!",r.json()['error'])
+
+        # Test wrong keytype
+        r = self.add_key(type='sdfdhhgj')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("Invalid keytype",r.json()['error'])
+
+        #Test unsupported algorithem
+        r = self.add_key(algo='lkjhgf')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("Unknown algorithm:",r.json()['error'])
+
+        #Test add a key and forgot bits
+        r = self.add_key(algo="rsasha256")
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("key requires the size (in bits) to be passed", r.json()['error'])
+
+        #Test wrong bit size
+        r = self.add_key(algo=10, bits=30)
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code,422)
+        self.assertIn("Wrong bit size!", r.json()['error'])
+
+        #Test can't guess key size
+        r = self.add_key(algo=15)
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code,422)
+        self.assertIn("Can't guess key size for algorithm", r.json()['error'])
+
+    def test_put_activate_deactivate_key(self):
+
+        #create key
+        try:
+            keyid = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "add-zone-key", Cryptokeys.zone, "ksk"])
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil add-zone-key failed: "+e.output)
+
+        # activate key
+        payload = {
+            'active': True
+        }
+        o = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(o.status_code, 200)
+
+        # check if key is activated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", Cryptokeys.zone])
+            self.assertTrue("Active" in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+        # deactivate key
+        payload2 = {
+            'active': False
+        }
+        q = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid),
+            data=json.dumps(payload2),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(q.status_code, 200)
+        self.assert_success_json(q)
+
+        # check if key is deactivated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", Cryptokeys.zone])
+            self.assertTrue("Inactive" in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+        # Remove it for further testing
+        try:
+            subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "remove-zone-key", Cryptokeys.zone, str(keyid)])
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil remove-zone-key failed: "+e.output)
+
+    def test_put_deactivate_deactivated_activate_activated_key(self):
+
+        #create key
+        try:
+            keyid = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "add-zone-key", Cryptokeys.zone, "ksk"])
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil add-zone-key failed: "+e.output)
+
+        # deactivate key
+        payload = {
+            'active': False
+        }
+        q = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(q.status_code, 200)
+        self.assert_success_json(q)
+
+        # check if key is still deactivated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", Cryptokeys.zone])
+            self.assertTrue("Inactive" in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+        # activate key
+        payload2 = {
+            'active': True
+        }
+        o = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid),
+            data=json.dumps(payload2),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(o.status_code, 200)
+
+        # check if key is activated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", Cryptokeys.zone])
+            self.assertTrue("Active" in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+        #activate again
+        z = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+Cryptokeys.zone+"/cryptokeys/"+keyid),
+            data=json.dumps(payload2),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(z.status_code, 200)
+
+        # check if key is still activated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", Cryptokeys.zone])
+            self.assertTrue("Active" in out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
\ No newline at end of file
index 04a851a9710c4d3829d4b259f52cc18ba5314e34..21f54ac379a2a40fe641a3ea677754f66088c22e 100644 (file)
@@ -30,6 +30,10 @@ class ApiTestCase(unittest.TestCase):
             raise
         self.assertEquals(result.headers['Content-Type'], 'application/json')
 
+    def assert_error_json(self, result):
+        self.assertTrue(400 <= result.status_code < 600, "Response has not an error code "+str(result.status_code))
+        self.assertEquals(result.headers['Content-Type'], 'application/json', "Response status code "+str(result.status_code))
+
     def assert_success(self, result):
         try:
             result.raise_for_status()