Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / userdata / tests.py @ 19b2c29d

History | View | Annotate | Download (9.8 kB)

1 b4b82ec4 Giorgos Korfiatis
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
2 c6c99d99 Vangelis Koukis
#
3 c6c99d99 Vangelis Koukis
# Redistribution and use in source and binary forms, with or
4 c6c99d99 Vangelis Koukis
# without modification, are permitted provided that the following
5 c6c99d99 Vangelis Koukis
# conditions are met:
6 c6c99d99 Vangelis Koukis
#
7 c6c99d99 Vangelis Koukis
#   1. Redistributions of source code must retain the above
8 c6c99d99 Vangelis Koukis
#      copyright notice, this list of conditions and the following
9 c6c99d99 Vangelis Koukis
#      disclaimer.
10 c6c99d99 Vangelis Koukis
#
11 c6c99d99 Vangelis Koukis
#   2. Redistributions in binary form must reproduce the above
12 c6c99d99 Vangelis Koukis
#      copyright notice, this list of conditions and the following
13 c6c99d99 Vangelis Koukis
#      disclaimer in the documentation and/or other materials
14 c6c99d99 Vangelis Koukis
#      provided with the distribution.
15 c6c99d99 Vangelis Koukis
#
16 c6c99d99 Vangelis Koukis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 c6c99d99 Vangelis Koukis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 c6c99d99 Vangelis Koukis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 c6c99d99 Vangelis Koukis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 c6c99d99 Vangelis Koukis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 c6c99d99 Vangelis Koukis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 c6c99d99 Vangelis Koukis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 c6c99d99 Vangelis Koukis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 c6c99d99 Vangelis Koukis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 c6c99d99 Vangelis Koukis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 c6c99d99 Vangelis Koukis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 c6c99d99 Vangelis Koukis
# POSSIBILITY OF SUCH DAMAGE.
28 c6c99d99 Vangelis Koukis
#
29 c6c99d99 Vangelis Koukis
# The views and conclusions contained in the software and
30 c6c99d99 Vangelis Koukis
# documentation are those of the authors and should not be
31 c6c99d99 Vangelis Koukis
# interpreted as representing official policies, either expressed
32 c6c99d99 Vangelis Koukis
# or implied, of GRNET S.A.
33 c6c99d99 Vangelis Koukis
#
34 eee0487e Kostas Papadimitriou
35 aaaf78f2 Giorgos Korfiatis
from django import http
36 39c542df Vangelis Koukis
from django.test import TransactionTestCase
37 eee0487e Kostas Papadimitriou
from django.conf import settings
38 eee0487e Kostas Papadimitriou
from django.test.client import Client
39 6ab78e7c Kostas Papadimitriou
from django.utils import simplejson as json
40 be2c0c51 Kostas Papadimitriou
from django.core.urlresolvers import reverse
41 a9d34f3b Kostas Papadimitriou
from django.core.validators import MaxLengthValidator
42 a9d34f3b Kostas Papadimitriou
43 a9d34f3b Kostas Papadimitriou
from snf_django.utils.testing import with_settings
44 a9d34f3b Kostas Papadimitriou
45 d495600d Ilias Tsitsimpis
from mock import patch
46 eee0487e Kostas Papadimitriou
47 a9d34f3b Kostas Papadimitriou
from synnefo.userdata.models import PublicKeyPair, SSH_KEY_MAX_CONTENT_LENGTH
48 244c552b Giorgos Verigakis
49 eee0487e Kostas Papadimitriou
50 d495600d Ilias Tsitsimpis
def get_user_mock(request, *args, **kwargs):
51 d495600d Ilias Tsitsimpis
    if request.META.get('HTTP_X_AUTH_TOKEN', None) == '0000':
52 d495600d Ilias Tsitsimpis
        request.user_uniq = 'test'
53 b4b82ec4 Giorgos Korfiatis
        request.user = {"access": {
54 b4b82ec4 Giorgos Korfiatis
                        "token": {
55 b4b82ec4 Giorgos Korfiatis
                            "expires": "2013-06-19T15:23:59.975572+00:00",
56 b4b82ec4 Giorgos Korfiatis
                            "id": "token",
57 b4b82ec4 Giorgos Korfiatis
                            "tenant": {
58 b4b82ec4 Giorgos Korfiatis
                                "id": "test",
59 b4b82ec4 Giorgos Korfiatis
                                "name": "Firstname Lastname"
60 b4b82ec4 Giorgos Korfiatis
                                }
61 b4b82ec4 Giorgos Korfiatis
                            },
62 b4b82ec4 Giorgos Korfiatis
                        "serviceCatalog": [],
63 b4b82ec4 Giorgos Korfiatis
                        "user": {
64 b4b82ec4 Giorgos Korfiatis
                            "roles_links": [],
65 b4b82ec4 Giorgos Korfiatis
                            "id": "test",
66 b4b82ec4 Giorgos Korfiatis
                            "roles": [{"id": 1, "name": "default"}],
67 b4b82ec4 Giorgos Korfiatis
                            "name": "Firstname Lastname"}}
68 b4b82ec4 Giorgos Korfiatis
                        }
69 d495600d Ilias Tsitsimpis
70 d495600d Ilias Tsitsimpis
71 eee0487e Kostas Papadimitriou
class AaiClient(Client):
72 eee0487e Kostas Papadimitriou
73 eee0487e Kostas Papadimitriou
    def request(self, **request):
74 d495600d Ilias Tsitsimpis
        # mock the astakos authentication function
75 d495600d Ilias Tsitsimpis
        with patch("synnefo.userdata.rest.get_user",
76 d495600d Ilias Tsitsimpis
                   new=get_user_mock):
77 d495600d Ilias Tsitsimpis
            with patch("synnefo.userdata.views.get_user",
78 d495600d Ilias Tsitsimpis
                       new=get_user_mock):
79 d495600d Ilias Tsitsimpis
                request['HTTP_X_AUTH_TOKEN'] = '0000'
80 d495600d Ilias Tsitsimpis
                return super(AaiClient, self).request(**request)
81 d495600d Ilias Tsitsimpis
82 eee0487e Kostas Papadimitriou
83 39c542df Vangelis Koukis
class TestRestViews(TransactionTestCase):
84 eee0487e Kostas Papadimitriou
85 eee0487e Kostas Papadimitriou
    fixtures = ['users']
86 eee0487e Kostas Papadimitriou
87 eee0487e Kostas Papadimitriou
    def setUp(self):
88 aaaf78f2 Giorgos Korfiatis
        settings.USERDATA_MAX_SSH_KEYS_PER_USER = 10
89 aaaf78f2 Giorgos Korfiatis
90 7469ff7d Kostas Papadimitriou
        settings.SKIP_SSH_VALIDATION = True
91 eee0487e Kostas Papadimitriou
        self.client = AaiClient()
92 244c552b Giorgos Verigakis
        self.user = 'test'
93 d194e869 Kostas Papadimitriou
        self.keys_url = reverse('ui_keys_collection')
94 eee0487e Kostas Papadimitriou
95 a9d34f3b Kostas Papadimitriou
    def test_key_content_length_limit(self):
96 a9d34f3b Kostas Papadimitriou
        # patch validator
97 a9d34f3b Kostas Papadimitriou
        PublicKeyPair._meta.fields[3].validators = [MaxLengthValidator(10)]
98 a9d34f3b Kostas Papadimitriou
        resp = self.client.post(self.keys_url,
99 a9d34f3b Kostas Papadimitriou
                                json.dumps({'name': 'key pair 2',
100 a9d34f3b Kostas Papadimitriou
                                            'content': """0123456789+"""}),
101 a9d34f3b Kostas Papadimitriou
                                content_type='application/json')
102 a9d34f3b Kostas Papadimitriou
        self.assertEqual(resp.status_code, 422)
103 a9d34f3b Kostas Papadimitriou
        resp = json.loads(resp.content)
104 a9d34f3b Kostas Papadimitriou
        assert 'errors' in resp
105 a9d34f3b Kostas Papadimitriou
        assert 'content' in resp['errors']
106 a9d34f3b Kostas Papadimitriou
        self.assertEqual(PublicKeyPair.objects.count(), 0)
107 a9d34f3b Kostas Papadimitriou
        PublicKeyPair._meta.fields[3].validators = \
108 a9d34f3b Kostas Papadimitriou
            [MaxLengthValidator(SSH_KEY_MAX_CONTENT_LENGTH)]
109 a9d34f3b Kostas Papadimitriou
110 eee0487e Kostas Papadimitriou
    def test_keys_collection_get(self):
111 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url)
112 eee0487e Kostas Papadimitriou
        self.assertEqual(resp.content, "[]")
113 eee0487e Kostas Papadimitriou
114 eee0487e Kostas Papadimitriou
        PublicKeyPair.objects.create(user=self.user, name="key pair 1",
115 d3e9d04b Ilias Tsitsimpis
                                     content="content1")
116 eee0487e Kostas Papadimitriou
117 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url)
118 d3e9d04b Ilias Tsitsimpis
        resp_list = json.loads(resp.content)
119 be2c0c51 Kostas Papadimitriou
        exp_list = [{"content": "content1", "id": 1,
120 d3e9d04b Ilias Tsitsimpis
                     "uri": self.keys_url + "/1", "name": "key pair 1",
121 d3e9d04b Ilias Tsitsimpis
                     "fingerprint": "unknown fingerprint"}]
122 be2c0c51 Kostas Papadimitriou
        self.assertEqual(resp_list, exp_list)
123 eee0487e Kostas Papadimitriou
124 eee0487e Kostas Papadimitriou
        PublicKeyPair.objects.create(user=self.user, name="key pair 2",
125 d3e9d04b Ilias Tsitsimpis
                                     content="content2")
126 eee0487e Kostas Papadimitriou
127 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url)
128 be2c0c51 Kostas Papadimitriou
        resp_list = json.loads(resp.content)
129 be2c0c51 Kostas Papadimitriou
        exp_list = [{"content": "content1", "id": 1,
130 be2c0c51 Kostas Papadimitriou
                     "uri": self.keys_url + "/1", "name": "key pair 1",
131 be2c0c51 Kostas Papadimitriou
                     "fingerprint": "unknown fingerprint"},
132 be2c0c51 Kostas Papadimitriou
                    {"content": "content2", "id": 2,
133 be2c0c51 Kostas Papadimitriou
                     "uri": self.keys_url + "/2",
134 be2c0c51 Kostas Papadimitriou
                     "name": "key pair 2",
135 be2c0c51 Kostas Papadimitriou
                     "fingerprint": "unknown fingerprint"}]
136 be2c0c51 Kostas Papadimitriou
137 be2c0c51 Kostas Papadimitriou
        self.assertEqual(resp_list, exp_list)
138 eee0487e Kostas Papadimitriou
139 eee0487e Kostas Papadimitriou
    def test_keys_resourse_get(self):
140 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url + "/1")
141 6ab78e7c Kostas Papadimitriou
        self.assertEqual(resp.status_code, 404)
142 6ab78e7c Kostas Papadimitriou
143 6ab78e7c Kostas Papadimitriou
        # create a public key
144 6ab78e7c Kostas Papadimitriou
        PublicKeyPair.objects.create(user=self.user, name="key pair 1",
145 d3e9d04b Ilias Tsitsimpis
                                     content="content1")
146 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url + "/1")
147 d3e9d04b Ilias Tsitsimpis
        resp_dict = json.loads(resp.content)
148 be2c0c51 Kostas Papadimitriou
        exp_dict = {"content": "content1", "id": 1,
149 be2c0c51 Kostas Papadimitriou
                    "uri": self.keys_url + "/1", "name": "key pair 1",
150 be2c0c51 Kostas Papadimitriou
                    "fingerprint": "unknown fingerprint"}
151 be2c0c51 Kostas Papadimitriou
        self.assertEqual(resp_dict, exp_dict)
152 6ab78e7c Kostas Papadimitriou
153 6ab78e7c Kostas Papadimitriou
        # update
154 be2c0c51 Kostas Papadimitriou
        resp = self.client.put(self.keys_url + "/1",
155 d3e9d04b Ilias Tsitsimpis
                               json.dumps({'name': 'key pair 1 new name'}),
156 be2c0c51 Kostas Papadimitriou
                               content_type='application/json')
157 be2c0c51 Kostas Papadimitriou
158 6ab78e7c Kostas Papadimitriou
        pk = PublicKeyPair.objects.get(pk=1)
159 6ab78e7c Kostas Papadimitriou
        self.assertEqual(pk.name, "key pair 1 new name")
160 6ab78e7c Kostas Papadimitriou
161 6ab78e7c Kostas Papadimitriou
        # delete
162 be2c0c51 Kostas Papadimitriou
        resp = self.client.delete(self.keys_url + "/1")
163 6ab78e7c Kostas Papadimitriou
        self.assertEqual(PublicKeyPair.objects.count(), 0)
164 6ab78e7c Kostas Papadimitriou
165 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url + "/1")
166 6ab78e7c Kostas Papadimitriou
        self.assertEqual(resp.status_code, 404)
167 6ab78e7c Kostas Papadimitriou
168 be2c0c51 Kostas Papadimitriou
        resp = self.client.get(self.keys_url)
169 6ab78e7c Kostas Papadimitriou
        self.assertEqual(resp.content, "[]")
170 9829e3b6 Kostas Papadimitriou
171 9829e3b6 Kostas Papadimitriou
        # test rest create
172 be2c0c51 Kostas Papadimitriou
        resp = self.client.post(self.keys_url,
173 d3e9d04b Ilias Tsitsimpis
                                json.dumps({'name': 'key pair 2',
174 d3e9d04b Ilias Tsitsimpis
                                            'content': """key 2 content"""}),
175 be2c0c51 Kostas Papadimitriou
                                content_type='application/json')
176 9829e3b6 Kostas Papadimitriou
        self.assertEqual(PublicKeyPair.objects.count(), 1)
177 aaaf78f2 Giorgos Korfiatis
        pk = PublicKeyPair.objects.get()
178 9829e3b6 Kostas Papadimitriou
        self.assertEqual(pk.name, "key pair 2")
179 9829e3b6 Kostas Papadimitriou
        self.assertEqual(pk.content, "key 2 content")
180 9829e3b6 Kostas Papadimitriou
181 3548024c Kostas Papadimitriou
    def test_generate_views(self):
182 3548024c Kostas Papadimitriou
        import base64
183 3548024c Kostas Papadimitriou
184 3548024c Kostas Papadimitriou
        # just test that
185 be2c0c51 Kostas Papadimitriou
        resp = self.client.post(self.keys_url + "/generate")
186 3548024c Kostas Papadimitriou
        self.assertNotEqual(resp, "")
187 3548024c Kostas Papadimitriou
188 3548024c Kostas Papadimitriou
        data = json.loads(resp.content)
189 d3e9d04b Ilias Tsitsimpis
        self.assertEqual('private' in data, True)
190 d3e9d04b Ilias Tsitsimpis
        self.assertEqual('private' in data, True)
191 3548024c Kostas Papadimitriou
192 3548024c Kostas Papadimitriou
        # public key is base64 encoded
193 d3e9d04b Ilias Tsitsimpis
        base64.b64decode(data['public'].replace("ssh-rsa ", ""))
194 3548024c Kostas Papadimitriou
195 3548024c Kostas Papadimitriou
        # remove header/footer
196 3548024c Kostas Papadimitriou
        private = "".join(data['private'].split("\n")[1:-1])
197 3548024c Kostas Papadimitriou
198 3548024c Kostas Papadimitriou
        # private key is base64 encoded
199 3548024c Kostas Papadimitriou
        base64.b64decode(private)
200 3548024c Kostas Papadimitriou
201 386481eb Kostas Papadimitriou
        new_key = PublicKeyPair()
202 386481eb Kostas Papadimitriou
        new_key.content = data['public']
203 386481eb Kostas Papadimitriou
        new_key.name = "new key"
204 244c552b Giorgos Verigakis
        new_key.user = 'test'
205 386481eb Kostas Papadimitriou
        new_key.full_clean()
206 386481eb Kostas Papadimitriou
        new_key.save()
207 386481eb Kostas Papadimitriou
208 aaaf78f2 Giorgos Korfiatis
    def test_generate_limit(self):
209 aaaf78f2 Giorgos Korfiatis
        settings.USERDATA_MAX_SSH_KEYS_PER_USER = 1
210 d3e9d04b Ilias Tsitsimpis
        self.client.post(self.keys_url,
211 d3e9d04b Ilias Tsitsimpis
                         json.dumps({'name': 'key1',
212 d3e9d04b Ilias Tsitsimpis
                                     'content': """key 1 content"""}),
213 d3e9d04b Ilias Tsitsimpis
                         content_type='application/json')
214 aaaf78f2 Giorgos Korfiatis
        genpath = self.keys_url + "/generate"
215 aaaf78f2 Giorgos Korfiatis
        r = self.client.post(genpath)
216 aaaf78f2 Giorgos Korfiatis
        assert isinstance(r, http.HttpResponseServerError)
217 aaaf78f2 Giorgos Korfiatis
218 c72a830d Kostas Papadimitriou
    def test_invalid_data(self):
219 be2c0c51 Kostas Papadimitriou
        resp = self.client.post(self.keys_url,
220 d3e9d04b Ilias Tsitsimpis
                                json.dumps({'content': """key 2 content"""}),
221 be2c0c51 Kostas Papadimitriou
                                content_type='application/json')
222 c72a830d Kostas Papadimitriou
223 a9d34f3b Kostas Papadimitriou
        self.assertEqual(resp.status_code, 422)
224 d3e9d04b Ilias Tsitsimpis
        self.assertEqual(resp.content,
225 d3e9d04b Ilias Tsitsimpis
                         """{"non_field_key": "__all__", "errors": """
226 d3e9d04b Ilias Tsitsimpis
                         """{"name": ["This field cannot be blank."]}}""")
227 c72a830d Kostas Papadimitriou
228 1a97a220 Kostas Papadimitriou
        settings.USERDATA_MAX_SSH_KEYS_PER_USER = 2
229 c72a830d Kostas Papadimitriou
230 c72a830d Kostas Papadimitriou
        # test ssh limit
231 be2c0c51 Kostas Papadimitriou
        resp = self.client.post(self.keys_url,
232 d3e9d04b Ilias Tsitsimpis
                                json.dumps({'name': 'key1',
233 d3e9d04b Ilias Tsitsimpis
                                            'content': """key 1 content"""}),
234 be2c0c51 Kostas Papadimitriou
                                content_type='application/json')
235 be2c0c51 Kostas Papadimitriou
        resp = self.client.post(self.keys_url,
236 d3e9d04b Ilias Tsitsimpis
                                json.dumps({'name': 'key1',
237 d3e9d04b Ilias Tsitsimpis
                                            'content': """key 1 content"""}),
238 be2c0c51 Kostas Papadimitriou
                                content_type='application/json')
239 be2c0c51 Kostas Papadimitriou
        resp = self.client.post(self.keys_url,
240 d3e9d04b Ilias Tsitsimpis
                                json.dumps({'name': 'key1',
241 d3e9d04b Ilias Tsitsimpis
                                            'content': """key 1 content"""}),
242 be2c0c51 Kostas Papadimitriou
                                content_type='application/json')
243 a9d34f3b Kostas Papadimitriou
        self.assertEqual(resp.status_code, 422)
244 d3e9d04b Ilias Tsitsimpis
        self.assertEqual(resp.content,
245 d3e9d04b Ilias Tsitsimpis
                         """{"non_field_key": "__all__", "errors": """
246 d3e9d04b Ilias Tsitsimpis
                         """{"__all__": ["SSH keys limit exceeded."]}}""")