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