]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | # -*- coding: utf-8 -*- |
2 | from __future__ import absolute_import | |
3 | ||
9f95a23c | 4 | import base64 |
11fdf7f2 | 5 | import logging |
9f95a23c | 6 | import time |
f67539c2 | 7 | from urllib import parse |
9f95a23c TL |
8 | |
9 | from cryptography.hazmat.backends import default_backend | |
9f95a23c | 10 | from cryptography.hazmat.primitives.hashes import SHA1 |
f67539c2 | 11 | from cryptography.hazmat.primitives.twofactor.totp import TOTP |
11fdf7f2 | 12 | |
f67539c2 | 13 | from .helper import DashboardTestCase, JLeaf, JList, JObj |
11fdf7f2 TL |
14 | |
15 | logger = logging.getLogger(__name__) | |
16 | ||
17 | ||
18 | class RgwTestCase(DashboardTestCase): | |
19 | ||
20 | maxDiff = None | |
21 | create_test_user = False | |
22 | ||
23 | AUTH_ROLES = ['rgw-manager'] | |
24 | ||
25 | @classmethod | |
26 | def setUpClass(cls): | |
27 | super(RgwTestCase, cls).setUpClass() | |
28 | # Create the administrator account. | |
29 | cls._radosgw_admin_cmd([ | |
30 | 'user', 'create', '--uid', 'admin', '--display-name', 'admin', | |
31 | '--system', '--access-key', 'admin', '--secret', 'admin' | |
32 | ]) | |
33 | # Update the dashboard configuration. | |
cd265ab1 TL |
34 | cls._ceph_cmd_with_secret(['dashboard', 'set-rgw-api-secret-key'], 'admin') |
35 | cls._ceph_cmd_with_secret(['dashboard', 'set-rgw-api-access-key'], 'admin') | |
11fdf7f2 TL |
36 | # Create a test user? |
37 | if cls.create_test_user: | |
38 | cls._radosgw_admin_cmd([ | |
39 | 'user', 'create', '--uid', 'teuth-test-user', '--display-name', | |
40 | 'teuth-test-user' | |
41 | ]) | |
42 | cls._radosgw_admin_cmd([ | |
43 | 'caps', 'add', '--uid', 'teuth-test-user', '--caps', | |
44 | 'metadata=write' | |
45 | ]) | |
46 | cls._radosgw_admin_cmd([ | |
47 | 'subuser', 'create', '--uid', 'teuth-test-user', '--subuser', | |
48 | 'teuth-test-subuser', '--access', 'full', '--key-type', 's3', | |
49 | '--access-key', 'xyz123' | |
50 | ]) | |
51 | cls._radosgw_admin_cmd([ | |
52 | 'subuser', 'create', '--uid', 'teuth-test-user', '--subuser', | |
53 | 'teuth-test-subuser2', '--access', 'full', '--key-type', | |
54 | 'swift' | |
55 | ]) | |
56 | ||
57 | @classmethod | |
58 | def tearDownClass(cls): | |
9f95a23c TL |
59 | # Delete administrator account. |
60 | cls._radosgw_admin_cmd(['user', 'rm', '--uid', 'admin']) | |
11fdf7f2 | 61 | if cls.create_test_user: |
9f95a23c | 62 | cls._radosgw_admin_cmd(['user', 'rm', '--uid=teuth-test-user', '--purge-data']) |
11fdf7f2 TL |
63 | super(RgwTestCase, cls).tearDownClass() |
64 | ||
f67539c2 TL |
65 | def get_rgw_user(self, uid, stats=True): |
66 | return self._get('/api/rgw/user/{}?stats={}'.format(uid, stats)) | |
11fdf7f2 TL |
67 | |
68 | ||
69 | class RgwApiCredentialsTest(RgwTestCase): | |
70 | ||
71 | AUTH_ROLES = ['rgw-manager'] | |
72 | ||
522d829b TL |
73 | def test_invalid_credentials(self): |
74 | self._ceph_cmd_with_secret(['dashboard', 'set-rgw-api-secret-key'], 'invalid') | |
75 | self._ceph_cmd_with_secret(['dashboard', 'set-rgw-api-access-key'], 'invalid') | |
11fdf7f2 | 76 | resp = self._get('/api/rgw/user') |
522d829b | 77 | self.assertStatus(404) |
11fdf7f2 TL |
78 | self.assertIn('detail', resp) |
79 | self.assertIn('component', resp) | |
522d829b | 80 | self.assertIn('Error connecting to Object Gateway', resp['detail']) |
11fdf7f2 TL |
81 | self.assertEqual(resp['component'], 'rgw') |
82 | ||
83 | def test_success(self): | |
522d829b TL |
84 | # Set the default credentials. |
85 | self._ceph_cmd_with_secret(['dashboard', 'set-rgw-api-secret-key'], 'admin') | |
86 | self._ceph_cmd_with_secret(['dashboard', 'set-rgw-api-access-key'], 'admin') | |
11fdf7f2 TL |
87 | data = self._get('/api/rgw/status') |
88 | self.assertStatus(200) | |
89 | self.assertIn('available', data) | |
90 | self.assertIn('message', data) | |
91 | self.assertTrue(data['available']) | |
92 | ||
11fdf7f2 | 93 | |
e306af50 TL |
94 | class RgwSiteTest(RgwTestCase): |
95 | ||
96 | AUTH_ROLES = ['rgw-manager'] | |
97 | ||
98 | def test_get_placement_targets(self): | |
99 | data = self._get('/api/rgw/site?query=placement-targets') | |
100 | self.assertStatus(200) | |
101 | self.assertSchema(data, JObj({ | |
102 | 'zonegroup': str, | |
103 | 'placement_targets': JList(JObj({ | |
104 | 'name': str, | |
105 | 'data_pool': str | |
106 | })) | |
107 | })) | |
108 | ||
109 | def test_get_realms(self): | |
110 | data = self._get('/api/rgw/site?query=realms') | |
111 | self.assertStatus(200) | |
112 | self.assertSchema(data, JList(str)) | |
113 | ||
114 | ||
11fdf7f2 TL |
115 | class RgwBucketTest(RgwTestCase): |
116 | ||
9f95a23c TL |
117 | _mfa_token_serial = '1' |
118 | _mfa_token_seed = '23456723' | |
1911f103 | 119 | _mfa_token_time_step = 2 |
9f95a23c | 120 | |
11fdf7f2 TL |
121 | AUTH_ROLES = ['rgw-manager'] |
122 | ||
123 | @classmethod | |
124 | def setUpClass(cls): | |
125 | cls.create_test_user = True | |
126 | super(RgwBucketTest, cls).setUpClass() | |
9f95a23c TL |
127 | # Create MFA TOTP token for test user. |
128 | cls._radosgw_admin_cmd([ | |
129 | 'mfa', 'create', '--uid', 'teuth-test-user', '--totp-serial', cls._mfa_token_serial, | |
130 | '--totp-seed', cls._mfa_token_seed, '--totp-seed-type', 'base32', | |
131 | '--totp-seconds', str(cls._mfa_token_time_step), '--totp-window', '1' | |
132 | ]) | |
eafe8130 | 133 | # Create tenanted users. |
11fdf7f2 TL |
134 | cls._radosgw_admin_cmd([ |
135 | 'user', 'create', '--tenant', 'testx', '--uid', 'teuth-test-user', | |
136 | '--display-name', 'tenanted teuth-test-user' | |
137 | ]) | |
eafe8130 | 138 | cls._radosgw_admin_cmd([ |
9f95a23c | 139 | 'user', 'create', '--tenant', 'testx2', '--uid', 'teuth-test-user2', |
eafe8130 TL |
140 | '--display-name', 'tenanted teuth-test-user 2' |
141 | ]) | |
11fdf7f2 TL |
142 | |
143 | @classmethod | |
144 | def tearDownClass(cls): | |
145 | cls._radosgw_admin_cmd( | |
9f95a23c | 146 | ['user', 'rm', '--tenant', 'testx', '--uid=teuth-test-user', '--purge-data']) |
eafe8130 | 147 | cls._radosgw_admin_cmd( |
9f95a23c | 148 | ['user', 'rm', '--tenant', 'testx2', '--uid=teuth-test-user2', '--purge-data']) |
11fdf7f2 TL |
149 | super(RgwBucketTest, cls).tearDownClass() |
150 | ||
9f95a23c TL |
151 | def _get_mfa_token_pin(self): |
152 | totp_key = base64.b32decode(self._mfa_token_seed) | |
153 | totp = TOTP(totp_key, 6, SHA1(), self._mfa_token_time_step, backend=default_backend(), | |
154 | enforce_key_length=False) | |
1911f103 | 155 | time_value = int(time.time()) |
9f95a23c TL |
156 | return totp.generate(time_value) |
157 | ||
11fdf7f2 TL |
158 | def test_all(self): |
159 | # Create a new bucket. | |
160 | self._post( | |
161 | '/api/rgw/bucket', | |
162 | params={ | |
163 | 'bucket': 'teuth-test-bucket', | |
9f95a23c TL |
164 | 'uid': 'admin', |
165 | 'zonegroup': 'default', | |
166 | 'placement_target': 'default-placement' | |
11fdf7f2 TL |
167 | }) |
168 | self.assertStatus(201) | |
169 | data = self.jsonBody() | |
170 | self.assertSchema(data, JObj(sub_elems={ | |
171 | 'bucket_info': JObj(sub_elems={ | |
172 | 'bucket': JObj(allow_unknown=True, sub_elems={ | |
173 | 'name': JLeaf(str), | |
174 | 'bucket_id': JLeaf(str), | |
175 | 'tenant': JLeaf(str) | |
176 | }), | |
177 | 'quota': JObj(sub_elems={}, allow_unknown=True), | |
178 | 'creation_time': JLeaf(str) | |
179 | }, allow_unknown=True) | |
180 | }, allow_unknown=True)) | |
181 | data = data['bucket_info']['bucket'] | |
182 | self.assertEqual(data['name'], 'teuth-test-bucket') | |
183 | self.assertEqual(data['tenant'], '') | |
184 | ||
185 | # List all buckets. | |
a4b75251 | 186 | data = self._get('/api/rgw/bucket', version='1.1') |
11fdf7f2 TL |
187 | self.assertStatus(200) |
188 | self.assertEqual(len(data), 1) | |
189 | self.assertIn('teuth-test-bucket', data) | |
190 | ||
f91f0fd5 | 191 | # List all buckets with stats. |
a4b75251 | 192 | data = self._get('/api/rgw/bucket?stats=true', version='1.1') |
f91f0fd5 TL |
193 | self.assertStatus(200) |
194 | self.assertEqual(len(data), 1) | |
195 | self.assertSchema(data[0], JObj(sub_elems={ | |
196 | 'bid': JLeaf(str), | |
197 | 'bucket': JLeaf(str), | |
198 | 'bucket_quota': JObj(sub_elems={}, allow_unknown=True), | |
199 | 'id': JLeaf(str), | |
200 | 'owner': JLeaf(str), | |
201 | 'usage': JObj(sub_elems={}, allow_unknown=True), | |
202 | 'tenant': JLeaf(str), | |
203 | }, allow_unknown=True)) | |
204 | ||
522d829b | 205 | # List all buckets names without stats. |
a4b75251 | 206 | data = self._get('/api/rgw/bucket?stats=false', version='1.1') |
522d829b TL |
207 | self.assertStatus(200) |
208 | self.assertEqual(data, ['teuth-test-bucket']) | |
209 | ||
11fdf7f2 TL |
210 | # Get the bucket. |
211 | data = self._get('/api/rgw/bucket/teuth-test-bucket') | |
212 | self.assertStatus(200) | |
213 | self.assertSchema(data, JObj(sub_elems={ | |
214 | 'id': JLeaf(str), | |
215 | 'bid': JLeaf(str), | |
216 | 'tenant': JLeaf(str), | |
217 | 'bucket': JLeaf(str), | |
218 | 'bucket_quota': JObj(sub_elems={}, allow_unknown=True), | |
f91f0fd5 TL |
219 | 'owner': JLeaf(str), |
220 | 'mfa_delete': JLeaf(str), | |
221 | 'usage': JObj(sub_elems={}, allow_unknown=True), | |
222 | 'versioning': JLeaf(str) | |
11fdf7f2 TL |
223 | }, allow_unknown=True)) |
224 | self.assertEqual(data['bucket'], 'teuth-test-bucket') | |
225 | self.assertEqual(data['owner'], 'admin') | |
9f95a23c TL |
226 | self.assertEqual(data['placement_rule'], 'default-placement') |
227 | self.assertEqual(data['versioning'], 'Suspended') | |
11fdf7f2 | 228 | |
9f95a23c | 229 | # Update bucket: change owner, enable versioning. |
11fdf7f2 TL |
230 | self._put( |
231 | '/api/rgw/bucket/teuth-test-bucket', | |
232 | params={ | |
233 | 'bucket_id': data['id'], | |
9f95a23c TL |
234 | 'uid': 'teuth-test-user', |
235 | 'versioning_state': 'Enabled' | |
11fdf7f2 TL |
236 | }) |
237 | self.assertStatus(200) | |
238 | data = self._get('/api/rgw/bucket/teuth-test-bucket') | |
239 | self.assertStatus(200) | |
240 | self.assertSchema(data, JObj(sub_elems={ | |
241 | 'owner': JLeaf(str), | |
242 | 'bid': JLeaf(str), | |
243 | 'tenant': JLeaf(str) | |
244 | }, allow_unknown=True)) | |
245 | self.assertEqual(data['owner'], 'teuth-test-user') | |
9f95a23c TL |
246 | self.assertEqual(data['versioning'], 'Enabled') |
247 | ||
248 | # Update bucket: enable MFA Delete. | |
249 | self._put( | |
250 | '/api/rgw/bucket/teuth-test-bucket', | |
251 | params={ | |
252 | 'bucket_id': data['id'], | |
253 | 'uid': 'teuth-test-user', | |
254 | 'versioning_state': 'Enabled', | |
255 | 'mfa_delete': 'Enabled', | |
256 | 'mfa_token_serial': self._mfa_token_serial, | |
257 | 'mfa_token_pin': self._get_mfa_token_pin() | |
258 | }) | |
259 | self.assertStatus(200) | |
260 | data = self._get('/api/rgw/bucket/teuth-test-bucket') | |
261 | self.assertStatus(200) | |
262 | self.assertEqual(data['versioning'], 'Enabled') | |
263 | self.assertEqual(data['mfa_delete'], 'Enabled') | |
264 | ||
265 | # Update bucket: disable versioning & MFA Delete. | |
1911f103 | 266 | time.sleep(self._mfa_token_time_step * 3) # Required to get new TOTP pin. |
9f95a23c TL |
267 | self._put( |
268 | '/api/rgw/bucket/teuth-test-bucket', | |
269 | params={ | |
270 | 'bucket_id': data['id'], | |
271 | 'uid': 'teuth-test-user', | |
272 | 'versioning_state': 'Suspended', | |
273 | 'mfa_delete': 'Disabled', | |
274 | 'mfa_token_serial': self._mfa_token_serial, | |
275 | 'mfa_token_pin': self._get_mfa_token_pin() | |
276 | }) | |
277 | self.assertStatus(200) | |
278 | data = self._get('/api/rgw/bucket/teuth-test-bucket') | |
279 | self.assertStatus(200) | |
280 | self.assertEqual(data['versioning'], 'Suspended') | |
281 | self.assertEqual(data['mfa_delete'], 'Disabled') | |
11fdf7f2 TL |
282 | |
283 | # Delete the bucket. | |
284 | self._delete('/api/rgw/bucket/teuth-test-bucket') | |
285 | self.assertStatus(204) | |
a4b75251 | 286 | data = self._get('/api/rgw/bucket', version='1.1') |
11fdf7f2 TL |
287 | self.assertStatus(200) |
288 | self.assertEqual(len(data), 0) | |
289 | ||
9f95a23c | 290 | def test_crud_w_tenant(self): |
11fdf7f2 TL |
291 | # Create a new bucket. The tenant of the user is used when |
292 | # the bucket is created. | |
293 | self._post( | |
294 | '/api/rgw/bucket', | |
295 | params={ | |
296 | 'bucket': 'teuth-test-bucket', | |
9f95a23c TL |
297 | 'uid': 'testx$teuth-test-user', |
298 | 'zonegroup': 'default', | |
299 | 'placement_target': 'default-placement' | |
11fdf7f2 TL |
300 | }) |
301 | self.assertStatus(201) | |
302 | # It's not possible to validate the result because there | |
303 | # IS NO result object returned by the RGW Admin OPS API | |
304 | # when a tenanted bucket is created. | |
305 | data = self.jsonBody() | |
306 | self.assertIsNone(data) | |
307 | ||
308 | # List all buckets. | |
a4b75251 | 309 | data = self._get('/api/rgw/bucket', version='1.1') |
11fdf7f2 TL |
310 | self.assertStatus(200) |
311 | self.assertEqual(len(data), 1) | |
312 | self.assertIn('testx/teuth-test-bucket', data) | |
313 | ||
9f95a23c TL |
314 | def _verify_tenant_bucket(bucket, tenant, uid): |
315 | full_bucket_name = '{}/{}'.format(tenant, bucket) | |
316 | _data = self._get('/api/rgw/bucket/{}'.format( | |
e306af50 | 317 | parse.quote_plus(full_bucket_name))) |
9f95a23c TL |
318 | self.assertStatus(200) |
319 | self.assertSchema(_data, JObj(sub_elems={ | |
320 | 'owner': JLeaf(str), | |
321 | 'bucket': JLeaf(str), | |
322 | 'tenant': JLeaf(str), | |
323 | 'bid': JLeaf(str) | |
324 | }, allow_unknown=True)) | |
325 | self.assertEqual(_data['owner'], '{}${}'.format(tenant, uid)) | |
326 | self.assertEqual(_data['bucket'], bucket) | |
327 | self.assertEqual(_data['tenant'], tenant) | |
328 | self.assertEqual(_data['bid'], full_bucket_name) | |
329 | return _data | |
330 | ||
11fdf7f2 | 331 | # Get the bucket. |
9f95a23c TL |
332 | data = _verify_tenant_bucket('teuth-test-bucket', 'testx', 'teuth-test-user') |
333 | self.assertEqual(data['placement_rule'], 'default-placement') | |
334 | self.assertEqual(data['versioning'], 'Suspended') | |
11fdf7f2 | 335 | |
9f95a23c | 336 | # Update bucket: different user with different tenant, enable versioning. |
eafe8130 TL |
337 | self._put( |
338 | '/api/rgw/bucket/{}'.format( | |
e306af50 | 339 | parse.quote_plus('testx/teuth-test-bucket')), |
eafe8130 TL |
340 | params={ |
341 | 'bucket_id': data['id'], | |
9f95a23c TL |
342 | 'uid': 'testx2$teuth-test-user2', |
343 | 'versioning_state': 'Enabled' | |
eafe8130 | 344 | }) |
9f95a23c TL |
345 | data = _verify_tenant_bucket('teuth-test-bucket', 'testx2', 'teuth-test-user2') |
346 | self.assertEqual(data['versioning'], 'Enabled') | |
eafe8130 | 347 | |
9f95a23c | 348 | # Change owner to a non-tenanted user |
11fdf7f2 TL |
349 | self._put( |
350 | '/api/rgw/bucket/{}'.format( | |
e306af50 | 351 | parse.quote_plus('testx2/teuth-test-bucket')), |
11fdf7f2 TL |
352 | params={ |
353 | 'bucket_id': data['id'], | |
354 | 'uid': 'admin' | |
355 | }) | |
356 | self.assertStatus(200) | |
9f95a23c | 357 | data = self._get('/api/rgw/bucket/teuth-test-bucket') |
11fdf7f2 TL |
358 | self.assertStatus(200) |
359 | self.assertIn('owner', data) | |
360 | self.assertEqual(data['owner'], 'admin') | |
9f95a23c TL |
361 | self.assertEqual(data['tenant'], '') |
362 | self.assertEqual(data['bucket'], 'teuth-test-bucket') | |
363 | self.assertEqual(data['bid'], 'teuth-test-bucket') | |
364 | self.assertEqual(data['versioning'], 'Enabled') | |
365 | ||
366 | # Change owner back to tenanted user, suspend versioning. | |
367 | self._put( | |
368 | '/api/rgw/bucket/teuth-test-bucket', | |
369 | params={ | |
370 | 'bucket_id': data['id'], | |
371 | 'uid': 'testx$teuth-test-user', | |
372 | 'versioning_state': 'Suspended' | |
373 | }) | |
374 | self.assertStatus(200) | |
375 | data = _verify_tenant_bucket('teuth-test-bucket', 'testx', 'teuth-test-user') | |
376 | self.assertEqual(data['versioning'], 'Suspended') | |
11fdf7f2 TL |
377 | |
378 | # Delete the bucket. | |
379 | self._delete('/api/rgw/bucket/{}'.format( | |
e306af50 | 380 | parse.quote_plus('testx/teuth-test-bucket'))) |
11fdf7f2 | 381 | self.assertStatus(204) |
a4b75251 | 382 | data = self._get('/api/rgw/bucket', version='1.1') |
11fdf7f2 TL |
383 | self.assertStatus(200) |
384 | self.assertEqual(len(data), 0) | |
385 | ||
9f95a23c TL |
386 | def test_crud_w_locking(self): |
387 | # Create | |
388 | self._post('/api/rgw/bucket', | |
389 | params={ | |
390 | 'bucket': 'teuth-test-bucket', | |
391 | 'uid': 'teuth-test-user', | |
392 | 'zonegroup': 'default', | |
393 | 'placement_target': 'default-placement', | |
394 | 'lock_enabled': 'true', | |
395 | 'lock_mode': 'GOVERNANCE', | |
396 | 'lock_retention_period_days': '0', | |
397 | 'lock_retention_period_years': '1' | |
398 | }) | |
399 | self.assertStatus(201) | |
400 | # Read | |
401 | data = self._get('/api/rgw/bucket/teuth-test-bucket') | |
402 | self.assertStatus(200) | |
403 | self.assertSchema( | |
404 | data, | |
405 | JObj(sub_elems={ | |
406 | 'lock_enabled': JLeaf(bool), | |
407 | 'lock_mode': JLeaf(str), | |
408 | 'lock_retention_period_days': JLeaf(int), | |
409 | 'lock_retention_period_years': JLeaf(int) | |
410 | }, | |
f67539c2 | 411 | allow_unknown=True)) |
9f95a23c TL |
412 | self.assertTrue(data['lock_enabled']) |
413 | self.assertEqual(data['lock_mode'], 'GOVERNANCE') | |
414 | self.assertEqual(data['lock_retention_period_days'], 0) | |
415 | self.assertEqual(data['lock_retention_period_years'], 1) | |
416 | # Update | |
417 | self._put('/api/rgw/bucket/teuth-test-bucket', | |
418 | params={ | |
419 | 'bucket_id': data['id'], | |
420 | 'uid': 'teuth-test-user', | |
421 | 'lock_mode': 'COMPLIANCE', | |
422 | 'lock_retention_period_days': '15', | |
423 | 'lock_retention_period_years': '0' | |
424 | }) | |
425 | self.assertStatus(200) | |
426 | data = self._get('/api/rgw/bucket/teuth-test-bucket') | |
427 | self.assertTrue(data['lock_enabled']) | |
428 | self.assertEqual(data['lock_mode'], 'COMPLIANCE') | |
429 | self.assertEqual(data['lock_retention_period_days'], 15) | |
430 | self.assertEqual(data['lock_retention_period_years'], 0) | |
431 | self.assertStatus(200) | |
b3b6e05e TL |
432 | |
433 | # Update: Disabling bucket versioning should fail if object locking enabled | |
434 | self._put('/api/rgw/bucket/teuth-test-bucket', | |
435 | params={ | |
436 | 'bucket_id': data['id'], | |
437 | 'uid': 'teuth-test-user', | |
438 | 'versioning_state': 'Suspended' | |
439 | }) | |
440 | self.assertStatus(409) | |
441 | ||
9f95a23c TL |
442 | # Delete |
443 | self._delete('/api/rgw/bucket/teuth-test-bucket') | |
444 | self.assertStatus(204) | |
445 | ||
11fdf7f2 | 446 | |
9f95a23c | 447 | class RgwDaemonTest(RgwTestCase): |
11fdf7f2 TL |
448 | |
449 | AUTH_ROLES = ['rgw-manager'] | |
450 | ||
451 | @DashboardTestCase.RunAs('test', 'test', [{ | |
452 | 'rgw': ['create', 'update', 'delete'] | |
453 | }]) | |
454 | def test_read_access_permissions(self): | |
455 | self._get('/api/rgw/daemon') | |
456 | self.assertStatus(403) | |
457 | self._get('/api/rgw/daemon/id') | |
458 | self.assertStatus(403) | |
459 | ||
460 | def test_list(self): | |
461 | data = self._get('/api/rgw/daemon') | |
462 | self.assertStatus(200) | |
463 | self.assertEqual(len(data), 1) | |
464 | data = data[0] | |
465 | self.assertIn('id', data) | |
466 | self.assertIn('version', data) | |
467 | self.assertIn('server_hostname', data) | |
f67539c2 TL |
468 | self.assertIn('zonegroup_name', data) |
469 | self.assertIn('zone_name', data) | |
11fdf7f2 TL |
470 | |
471 | def test_get(self): | |
472 | data = self._get('/api/rgw/daemon') | |
473 | self.assertStatus(200) | |
474 | ||
475 | data = self._get('/api/rgw/daemon/{}'.format(data[0]['id'])) | |
476 | self.assertStatus(200) | |
477 | self.assertIn('rgw_metadata', data) | |
478 | self.assertIn('rgw_id', data) | |
479 | self.assertIn('rgw_status', data) | |
480 | self.assertTrue(data['rgw_metadata']) | |
481 | ||
482 | def test_status(self): | |
11fdf7f2 TL |
483 | data = self._get('/api/rgw/status') |
484 | self.assertStatus(200) | |
485 | self.assertIn('available', data) | |
486 | self.assertIn('message', data) | |
487 | self.assertTrue(data['available']) | |
488 | ||
489 | ||
490 | class RgwUserTest(RgwTestCase): | |
491 | ||
492 | AUTH_ROLES = ['rgw-manager'] | |
493 | ||
494 | @classmethod | |
495 | def setUpClass(cls): | |
496 | super(RgwUserTest, cls).setUpClass() | |
497 | ||
498 | def _assert_user_data(self, data): | |
499 | self.assertSchema(data, JObj(sub_elems={ | |
500 | 'caps': JList(JObj(sub_elems={}, allow_unknown=True)), | |
501 | 'display_name': JLeaf(str), | |
502 | 'email': JLeaf(str), | |
503 | 'keys': JList(JObj(sub_elems={}, allow_unknown=True)), | |
504 | 'max_buckets': JLeaf(int), | |
505 | 'subusers': JList(JLeaf(str)), | |
506 | 'suspended': JLeaf(int), | |
507 | 'swift_keys': JList(JObj(sub_elems={}, allow_unknown=True)), | |
508 | 'tenant': JLeaf(str), | |
509 | 'user_id': JLeaf(str), | |
510 | 'uid': JLeaf(str) | |
511 | }, allow_unknown=True)) | |
512 | self.assertGreaterEqual(len(data['keys']), 1) | |
513 | ||
514 | def test_get(self): | |
515 | data = self.get_rgw_user('admin') | |
516 | self.assertStatus(200) | |
517 | self._assert_user_data(data) | |
518 | self.assertEqual(data['user_id'], 'admin') | |
f67539c2 TL |
519 | self.assertTrue(data['stats']) |
520 | self.assertIsInstance(data['stats'], dict) | |
521 | # Test without stats. | |
522 | data = self.get_rgw_user('admin', False) | |
523 | self.assertStatus(200) | |
524 | self._assert_user_data(data) | |
525 | self.assertEqual(data['user_id'], 'admin') | |
11fdf7f2 TL |
526 | |
527 | def test_list(self): | |
528 | data = self._get('/api/rgw/user') | |
529 | self.assertStatus(200) | |
530 | self.assertGreaterEqual(len(data), 1) | |
531 | self.assertIn('admin', data) | |
532 | ||
f6b5b4d7 TL |
533 | def test_get_emails(self): |
534 | data = self._get('/api/rgw/user/get_emails') | |
535 | self.assertStatus(200) | |
536 | self.assertSchema(data, JList(str)) | |
537 | ||
11fdf7f2 TL |
538 | def test_create_get_update_delete(self): |
539 | # Create a new user. | |
540 | self._post('/api/rgw/user', params={ | |
541 | 'uid': 'teuth-test-user', | |
542 | 'display_name': 'display name' | |
543 | }) | |
544 | self.assertStatus(201) | |
545 | data = self.jsonBody() | |
546 | self._assert_user_data(data) | |
547 | self.assertEqual(data['user_id'], 'teuth-test-user') | |
548 | self.assertEqual(data['display_name'], 'display name') | |
549 | ||
550 | # Get the user. | |
551 | data = self.get_rgw_user('teuth-test-user') | |
552 | self.assertStatus(200) | |
553 | self._assert_user_data(data) | |
554 | self.assertEqual(data['tenant'], '') | |
555 | self.assertEqual(data['user_id'], 'teuth-test-user') | |
556 | self.assertEqual(data['uid'], 'teuth-test-user') | |
557 | ||
558 | # Update the user. | |
559 | self._put( | |
560 | '/api/rgw/user/teuth-test-user', | |
561 | params={'display_name': 'new name'}) | |
562 | self.assertStatus(200) | |
563 | data = self.jsonBody() | |
564 | self._assert_user_data(data) | |
565 | self.assertEqual(data['display_name'], 'new name') | |
566 | ||
567 | # Delete the user. | |
568 | self._delete('/api/rgw/user/teuth-test-user') | |
569 | self.assertStatus(204) | |
570 | self.get_rgw_user('teuth-test-user') | |
571 | self.assertStatus(500) | |
572 | resp = self.jsonBody() | |
573 | self.assertIn('detail', resp) | |
574 | self.assertIn('failed request with status code 404', resp['detail']) | |
575 | self.assertIn('"Code":"NoSuchUser"', resp['detail']) | |
576 | self.assertIn('"HostId"', resp['detail']) | |
577 | self.assertIn('"RequestId"', resp['detail']) | |
578 | ||
579 | def test_create_get_update_delete_w_tenant(self): | |
580 | # Create a new user. | |
581 | self._post( | |
582 | '/api/rgw/user', | |
583 | params={ | |
584 | 'uid': 'test01$teuth-test-user', | |
585 | 'display_name': 'display name' | |
586 | }) | |
587 | self.assertStatus(201) | |
588 | data = self.jsonBody() | |
589 | self._assert_user_data(data) | |
590 | self.assertEqual(data['user_id'], 'teuth-test-user') | |
591 | self.assertEqual(data['display_name'], 'display name') | |
592 | ||
593 | # Get the user. | |
594 | data = self.get_rgw_user('test01$teuth-test-user') | |
595 | self.assertStatus(200) | |
596 | self._assert_user_data(data) | |
597 | self.assertEqual(data['tenant'], 'test01') | |
598 | self.assertEqual(data['user_id'], 'teuth-test-user') | |
599 | self.assertEqual(data['uid'], 'test01$teuth-test-user') | |
600 | ||
601 | # Update the user. | |
602 | self._put( | |
603 | '/api/rgw/user/test01$teuth-test-user', | |
604 | params={'display_name': 'new name'}) | |
605 | self.assertStatus(200) | |
606 | data = self.jsonBody() | |
607 | self._assert_user_data(data) | |
608 | self.assertEqual(data['display_name'], 'new name') | |
609 | ||
610 | # Delete the user. | |
611 | self._delete('/api/rgw/user/test01$teuth-test-user') | |
612 | self.assertStatus(204) | |
613 | self.get_rgw_user('test01$teuth-test-user') | |
614 | self.assertStatus(500) | |
615 | resp = self.jsonBody() | |
616 | self.assertIn('detail', resp) | |
617 | self.assertIn('failed request with status code 404', resp['detail']) | |
618 | self.assertIn('"Code":"NoSuchUser"', resp['detail']) | |
619 | self.assertIn('"HostId"', resp['detail']) | |
620 | self.assertIn('"RequestId"', resp['detail']) | |
621 | ||
622 | ||
623 | class RgwUserCapabilityTest(RgwTestCase): | |
624 | ||
625 | AUTH_ROLES = ['rgw-manager'] | |
626 | ||
627 | @classmethod | |
628 | def setUpClass(cls): | |
629 | cls.create_test_user = True | |
630 | super(RgwUserCapabilityTest, cls).setUpClass() | |
631 | ||
632 | def test_set(self): | |
633 | self._post( | |
634 | '/api/rgw/user/teuth-test-user/capability', | |
635 | params={ | |
636 | 'type': 'usage', | |
637 | 'perm': 'read' | |
638 | }) | |
639 | self.assertStatus(201) | |
640 | data = self.jsonBody() | |
641 | self.assertEqual(len(data), 1) | |
642 | data = data[0] | |
643 | self.assertEqual(data['type'], 'usage') | |
644 | self.assertEqual(data['perm'], 'read') | |
645 | ||
646 | # Get the user data to validate the capabilities. | |
647 | data = self.get_rgw_user('teuth-test-user') | |
648 | self.assertStatus(200) | |
649 | self.assertGreaterEqual(len(data['caps']), 1) | |
650 | self.assertEqual(data['caps'][0]['type'], 'usage') | |
651 | self.assertEqual(data['caps'][0]['perm'], 'read') | |
652 | ||
653 | def test_delete(self): | |
654 | self._delete( | |
655 | '/api/rgw/user/teuth-test-user/capability', | |
656 | params={ | |
657 | 'type': 'metadata', | |
658 | 'perm': 'write' | |
659 | }) | |
660 | self.assertStatus(204) | |
661 | ||
662 | # Get the user data to validate the capabilities. | |
663 | data = self.get_rgw_user('teuth-test-user') | |
664 | self.assertStatus(200) | |
665 | self.assertEqual(len(data['caps']), 0) | |
666 | ||
667 | ||
668 | class RgwUserKeyTest(RgwTestCase): | |
669 | ||
670 | AUTH_ROLES = ['rgw-manager'] | |
671 | ||
672 | @classmethod | |
673 | def setUpClass(cls): | |
674 | cls.create_test_user = True | |
675 | super(RgwUserKeyTest, cls).setUpClass() | |
676 | ||
677 | def test_create_s3(self): | |
678 | self._post( | |
679 | '/api/rgw/user/teuth-test-user/key', | |
680 | params={ | |
681 | 'key_type': 's3', | |
682 | 'generate_key': 'false', | |
683 | 'access_key': 'abc987', | |
684 | 'secret_key': 'aaabbbccc' | |
685 | }) | |
686 | data = self.jsonBody() | |
687 | self.assertStatus(201) | |
688 | self.assertGreaterEqual(len(data), 3) | |
689 | key = self.find_object_in_list('access_key', 'abc987', data) | |
690 | self.assertIsInstance(key, object) | |
691 | self.assertEqual(key['secret_key'], 'aaabbbccc') | |
692 | ||
693 | def test_create_swift(self): | |
694 | self._post( | |
695 | '/api/rgw/user/teuth-test-user/key', | |
696 | params={ | |
697 | 'key_type': 'swift', | |
698 | 'subuser': 'teuth-test-subuser', | |
699 | 'generate_key': 'false', | |
700 | 'secret_key': 'xxxyyyzzz' | |
701 | }) | |
702 | data = self.jsonBody() | |
703 | self.assertStatus(201) | |
704 | self.assertGreaterEqual(len(data), 2) | |
705 | key = self.find_object_in_list('secret_key', 'xxxyyyzzz', data) | |
706 | self.assertIsInstance(key, object) | |
707 | ||
708 | def test_delete_s3(self): | |
709 | self._delete( | |
710 | '/api/rgw/user/teuth-test-user/key', | |
711 | params={ | |
712 | 'key_type': 's3', | |
713 | 'access_key': 'xyz123' | |
714 | }) | |
715 | self.assertStatus(204) | |
716 | ||
717 | def test_delete_swift(self): | |
718 | self._delete( | |
719 | '/api/rgw/user/teuth-test-user/key', | |
720 | params={ | |
721 | 'key_type': 'swift', | |
722 | 'subuser': 'teuth-test-user:teuth-test-subuser2' | |
723 | }) | |
724 | self.assertStatus(204) | |
725 | ||
726 | ||
727 | class RgwUserQuotaTest(RgwTestCase): | |
728 | ||
729 | AUTH_ROLES = ['rgw-manager'] | |
730 | ||
731 | @classmethod | |
732 | def setUpClass(cls): | |
733 | cls.create_test_user = True | |
734 | super(RgwUserQuotaTest, cls).setUpClass() | |
735 | ||
736 | def _assert_quota(self, data): | |
737 | self.assertIn('user_quota', data) | |
738 | self.assertIn('max_objects', data['user_quota']) | |
739 | self.assertIn('enabled', data['user_quota']) | |
740 | self.assertIn('max_size_kb', data['user_quota']) | |
741 | self.assertIn('max_size', data['user_quota']) | |
742 | self.assertIn('bucket_quota', data) | |
743 | self.assertIn('max_objects', data['bucket_quota']) | |
744 | self.assertIn('enabled', data['bucket_quota']) | |
745 | self.assertIn('max_size_kb', data['bucket_quota']) | |
746 | self.assertIn('max_size', data['bucket_quota']) | |
747 | ||
748 | def test_get_quota(self): | |
749 | data = self._get('/api/rgw/user/teuth-test-user/quota') | |
750 | self.assertStatus(200) | |
751 | self._assert_quota(data) | |
752 | ||
753 | def test_set_user_quota(self): | |
754 | self._put( | |
755 | '/api/rgw/user/teuth-test-user/quota', | |
756 | params={ | |
757 | 'quota_type': 'user', | |
758 | 'enabled': 'true', | |
759 | 'max_size_kb': 2048, | |
760 | 'max_objects': 101 | |
761 | }) | |
762 | self.assertStatus(200) | |
763 | ||
764 | data = self._get('/api/rgw/user/teuth-test-user/quota') | |
765 | self.assertStatus(200) | |
766 | self._assert_quota(data) | |
767 | self.assertEqual(data['user_quota']['max_objects'], 101) | |
768 | self.assertTrue(data['user_quota']['enabled']) | |
769 | self.assertEqual(data['user_quota']['max_size_kb'], 2048) | |
770 | ||
771 | def test_set_bucket_quota(self): | |
772 | self._put( | |
773 | '/api/rgw/user/teuth-test-user/quota', | |
774 | params={ | |
775 | 'quota_type': 'bucket', | |
776 | 'enabled': 'false', | |
777 | 'max_size_kb': 4096, | |
778 | 'max_objects': 2000 | |
779 | }) | |
780 | self.assertStatus(200) | |
781 | ||
782 | data = self._get('/api/rgw/user/teuth-test-user/quota') | |
783 | self.assertStatus(200) | |
784 | self._assert_quota(data) | |
785 | self.assertEqual(data['bucket_quota']['max_objects'], 2000) | |
786 | self.assertFalse(data['bucket_quota']['enabled']) | |
787 | self.assertEqual(data['bucket_quota']['max_size_kb'], 4096) | |
788 | ||
789 | ||
790 | class RgwUserSubuserTest(RgwTestCase): | |
791 | ||
792 | AUTH_ROLES = ['rgw-manager'] | |
793 | ||
794 | @classmethod | |
795 | def setUpClass(cls): | |
796 | cls.create_test_user = True | |
797 | super(RgwUserSubuserTest, cls).setUpClass() | |
798 | ||
799 | def test_create_swift(self): | |
800 | self._post( | |
801 | '/api/rgw/user/teuth-test-user/subuser', | |
802 | params={ | |
803 | 'subuser': 'tux', | |
804 | 'access': 'readwrite', | |
805 | 'key_type': 'swift' | |
806 | }) | |
807 | self.assertStatus(201) | |
808 | data = self.jsonBody() | |
809 | subuser = self.find_object_in_list('id', 'teuth-test-user:tux', data) | |
810 | self.assertIsInstance(subuser, object) | |
811 | self.assertEqual(subuser['permissions'], 'read-write') | |
812 | ||
813 | # Get the user data to validate the keys. | |
814 | data = self.get_rgw_user('teuth-test-user') | |
815 | self.assertStatus(200) | |
816 | key = self.find_object_in_list('user', 'teuth-test-user:tux', | |
817 | data['swift_keys']) | |
818 | self.assertIsInstance(key, object) | |
819 | ||
820 | def test_create_s3(self): | |
821 | self._post( | |
822 | '/api/rgw/user/teuth-test-user/subuser', | |
823 | params={ | |
824 | 'subuser': 'hugo', | |
825 | 'access': 'write', | |
826 | 'generate_secret': 'false', | |
827 | 'access_key': 'yyy', | |
828 | 'secret_key': 'xxx' | |
829 | }) | |
830 | self.assertStatus(201) | |
831 | data = self.jsonBody() | |
832 | subuser = self.find_object_in_list('id', 'teuth-test-user:hugo', data) | |
833 | self.assertIsInstance(subuser, object) | |
834 | self.assertEqual(subuser['permissions'], 'write') | |
835 | ||
836 | # Get the user data to validate the keys. | |
837 | data = self.get_rgw_user('teuth-test-user') | |
838 | self.assertStatus(200) | |
839 | key = self.find_object_in_list('user', 'teuth-test-user:hugo', | |
840 | data['keys']) | |
841 | self.assertIsInstance(key, object) | |
842 | self.assertEqual(key['secret_key'], 'xxx') | |
843 | ||
844 | def test_delete_w_purge(self): | |
845 | self._delete( | |
846 | '/api/rgw/user/teuth-test-user/subuser/teuth-test-subuser2') | |
847 | self.assertStatus(204) | |
848 | ||
849 | # Get the user data to check that the keys don't exist anymore. | |
850 | data = self.get_rgw_user('teuth-test-user') | |
851 | self.assertStatus(200) | |
852 | key = self.find_object_in_list( | |
853 | 'user', 'teuth-test-user:teuth-test-subuser2', data['swift_keys']) | |
854 | self.assertIsNone(key) | |
855 | ||
856 | def test_delete_wo_purge(self): | |
857 | self._delete( | |
858 | '/api/rgw/user/teuth-test-user/subuser/teuth-test-subuser', | |
859 | params={'purge_keys': 'false'}) | |
860 | self.assertStatus(204) | |
861 | ||
862 | # Get the user data to check whether they keys still exist. | |
863 | data = self.get_rgw_user('teuth-test-user') | |
864 | self.assertStatus(200) | |
865 | key = self.find_object_in_list( | |
866 | 'user', 'teuth-test-user:teuth-test-subuser', data['keys']) | |
867 | self.assertIsInstance(key, object) |