]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/mgr/dashboard/test_rgw.py
update ceph source to reef 18.1.2
[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
f67539c2 7from urllib import parse
9f95a23c
TL
8
9from cryptography.hazmat.backends import default_backend
9f95a23c 10from cryptography.hazmat.primitives.hashes import SHA1
f67539c2 11from cryptography.hazmat.primitives.twofactor.totp import TOTP
11fdf7f2 12
f67539c2 13from .helper import DashboardTestCase, JLeaf, JList, JObj
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.
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
69class 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')
2a845540 87 data = self._get('/ui-api/rgw/status')
11fdf7f2
TL
88 self.assertStatus(200)
89 self.assertIn('available', data)
90 self.assertIn('message', data)
91 self.assertTrue(data['available'])
92
11fdf7f2 93
e306af50
TL
94class 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
115class 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 447class 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)
1e59de90 470 self.assertIn('port', data)
11fdf7f2
TL
471
472 def test_get(self):
473 data = self._get('/api/rgw/daemon')
474 self.assertStatus(200)
475
476 data = self._get('/api/rgw/daemon/{}'.format(data[0]['id']))
477 self.assertStatus(200)
478 self.assertIn('rgw_metadata', data)
479 self.assertIn('rgw_id', data)
480 self.assertIn('rgw_status', data)
481 self.assertTrue(data['rgw_metadata'])
482
483 def test_status(self):
2a845540 484 data = self._get('/ui-api/rgw/status')
11fdf7f2
TL
485 self.assertStatus(200)
486 self.assertIn('available', data)
487 self.assertIn('message', data)
488 self.assertTrue(data['available'])
489
490
491class RgwUserTest(RgwTestCase):
492
493 AUTH_ROLES = ['rgw-manager']
494
495 @classmethod
496 def setUpClass(cls):
497 super(RgwUserTest, cls).setUpClass()
498
499 def _assert_user_data(self, data):
500 self.assertSchema(data, JObj(sub_elems={
501 'caps': JList(JObj(sub_elems={}, allow_unknown=True)),
502 'display_name': JLeaf(str),
503 'email': JLeaf(str),
504 'keys': JList(JObj(sub_elems={}, allow_unknown=True)),
505 'max_buckets': JLeaf(int),
506 'subusers': JList(JLeaf(str)),
507 'suspended': JLeaf(int),
508 'swift_keys': JList(JObj(sub_elems={}, allow_unknown=True)),
509 'tenant': JLeaf(str),
510 'user_id': JLeaf(str),
511 'uid': JLeaf(str)
512 }, allow_unknown=True))
513 self.assertGreaterEqual(len(data['keys']), 1)
514
515 def test_get(self):
516 data = self.get_rgw_user('admin')
517 self.assertStatus(200)
518 self._assert_user_data(data)
519 self.assertEqual(data['user_id'], 'admin')
f67539c2
TL
520 self.assertTrue(data['stats'])
521 self.assertIsInstance(data['stats'], dict)
522 # Test without stats.
523 data = self.get_rgw_user('admin', False)
524 self.assertStatus(200)
525 self._assert_user_data(data)
526 self.assertEqual(data['user_id'], 'admin')
11fdf7f2
TL
527
528 def test_list(self):
529 data = self._get('/api/rgw/user')
530 self.assertStatus(200)
531 self.assertGreaterEqual(len(data), 1)
532 self.assertIn('admin', data)
533
f6b5b4d7
TL
534 def test_get_emails(self):
535 data = self._get('/api/rgw/user/get_emails')
536 self.assertStatus(200)
537 self.assertSchema(data, JList(str))
538
11fdf7f2
TL
539 def test_create_get_update_delete(self):
540 # Create a new user.
541 self._post('/api/rgw/user', params={
542 'uid': 'teuth-test-user',
543 'display_name': 'display name'
544 })
545 self.assertStatus(201)
546 data = self.jsonBody()
547 self._assert_user_data(data)
548 self.assertEqual(data['user_id'], 'teuth-test-user')
549 self.assertEqual(data['display_name'], 'display name')
550
551 # Get the user.
552 data = self.get_rgw_user('teuth-test-user')
553 self.assertStatus(200)
554 self._assert_user_data(data)
555 self.assertEqual(data['tenant'], '')
556 self.assertEqual(data['user_id'], 'teuth-test-user')
557 self.assertEqual(data['uid'], 'teuth-test-user')
558
559 # Update the user.
560 self._put(
561 '/api/rgw/user/teuth-test-user',
562 params={'display_name': 'new name'})
563 self.assertStatus(200)
564 data = self.jsonBody()
565 self._assert_user_data(data)
566 self.assertEqual(data['display_name'], 'new name')
567
568 # Delete the user.
569 self._delete('/api/rgw/user/teuth-test-user')
570 self.assertStatus(204)
571 self.get_rgw_user('teuth-test-user')
572 self.assertStatus(500)
573 resp = self.jsonBody()
574 self.assertIn('detail', resp)
575 self.assertIn('failed request with status code 404', resp['detail'])
576 self.assertIn('"Code":"NoSuchUser"', resp['detail'])
577 self.assertIn('"HostId"', resp['detail'])
578 self.assertIn('"RequestId"', resp['detail'])
579
580 def test_create_get_update_delete_w_tenant(self):
581 # Create a new user.
582 self._post(
583 '/api/rgw/user',
584 params={
585 'uid': 'test01$teuth-test-user',
586 'display_name': 'display name'
587 })
588 self.assertStatus(201)
589 data = self.jsonBody()
590 self._assert_user_data(data)
591 self.assertEqual(data['user_id'], 'teuth-test-user')
592 self.assertEqual(data['display_name'], 'display name')
593
594 # Get the user.
595 data = self.get_rgw_user('test01$teuth-test-user')
596 self.assertStatus(200)
597 self._assert_user_data(data)
598 self.assertEqual(data['tenant'], 'test01')
599 self.assertEqual(data['user_id'], 'teuth-test-user')
600 self.assertEqual(data['uid'], 'test01$teuth-test-user')
601
602 # Update the user.
603 self._put(
604 '/api/rgw/user/test01$teuth-test-user',
605 params={'display_name': 'new name'})
606 self.assertStatus(200)
607 data = self.jsonBody()
608 self._assert_user_data(data)
609 self.assertEqual(data['display_name'], 'new name')
610
611 # Delete the user.
612 self._delete('/api/rgw/user/test01$teuth-test-user')
613 self.assertStatus(204)
614 self.get_rgw_user('test01$teuth-test-user')
615 self.assertStatus(500)
616 resp = self.jsonBody()
617 self.assertIn('detail', resp)
618 self.assertIn('failed request with status code 404', resp['detail'])
619 self.assertIn('"Code":"NoSuchUser"', resp['detail'])
620 self.assertIn('"HostId"', resp['detail'])
621 self.assertIn('"RequestId"', resp['detail'])
622
623
624class RgwUserCapabilityTest(RgwTestCase):
625
626 AUTH_ROLES = ['rgw-manager']
627
628 @classmethod
629 def setUpClass(cls):
630 cls.create_test_user = True
631 super(RgwUserCapabilityTest, cls).setUpClass()
632
633 def test_set(self):
634 self._post(
635 '/api/rgw/user/teuth-test-user/capability',
636 params={
637 'type': 'usage',
638 'perm': 'read'
639 })
640 self.assertStatus(201)
641 data = self.jsonBody()
642 self.assertEqual(len(data), 1)
643 data = data[0]
644 self.assertEqual(data['type'], 'usage')
645 self.assertEqual(data['perm'], 'read')
646
647 # Get the user data to validate the capabilities.
648 data = self.get_rgw_user('teuth-test-user')
649 self.assertStatus(200)
650 self.assertGreaterEqual(len(data['caps']), 1)
651 self.assertEqual(data['caps'][0]['type'], 'usage')
652 self.assertEqual(data['caps'][0]['perm'], 'read')
653
654 def test_delete(self):
655 self._delete(
656 '/api/rgw/user/teuth-test-user/capability',
657 params={
658 'type': 'metadata',
659 'perm': 'write'
660 })
661 self.assertStatus(204)
662
663 # Get the user data to validate the capabilities.
664 data = self.get_rgw_user('teuth-test-user')
665 self.assertStatus(200)
666 self.assertEqual(len(data['caps']), 0)
667
668
669class RgwUserKeyTest(RgwTestCase):
670
671 AUTH_ROLES = ['rgw-manager']
672
673 @classmethod
674 def setUpClass(cls):
675 cls.create_test_user = True
676 super(RgwUserKeyTest, cls).setUpClass()
677
678 def test_create_s3(self):
679 self._post(
680 '/api/rgw/user/teuth-test-user/key',
681 params={
682 'key_type': 's3',
683 'generate_key': 'false',
684 'access_key': 'abc987',
685 'secret_key': 'aaabbbccc'
686 })
687 data = self.jsonBody()
688 self.assertStatus(201)
689 self.assertGreaterEqual(len(data), 3)
690 key = self.find_object_in_list('access_key', 'abc987', data)
691 self.assertIsInstance(key, object)
692 self.assertEqual(key['secret_key'], 'aaabbbccc')
693
694 def test_create_swift(self):
695 self._post(
696 '/api/rgw/user/teuth-test-user/key',
697 params={
698 'key_type': 'swift',
699 'subuser': 'teuth-test-subuser',
700 'generate_key': 'false',
701 'secret_key': 'xxxyyyzzz'
702 })
703 data = self.jsonBody()
704 self.assertStatus(201)
705 self.assertGreaterEqual(len(data), 2)
706 key = self.find_object_in_list('secret_key', 'xxxyyyzzz', data)
707 self.assertIsInstance(key, object)
708
709 def test_delete_s3(self):
710 self._delete(
711 '/api/rgw/user/teuth-test-user/key',
712 params={
713 'key_type': 's3',
714 'access_key': 'xyz123'
715 })
716 self.assertStatus(204)
717
718 def test_delete_swift(self):
719 self._delete(
720 '/api/rgw/user/teuth-test-user/key',
721 params={
722 'key_type': 'swift',
723 'subuser': 'teuth-test-user:teuth-test-subuser2'
724 })
725 self.assertStatus(204)
726
727
728class RgwUserQuotaTest(RgwTestCase):
729
730 AUTH_ROLES = ['rgw-manager']
731
732 @classmethod
733 def setUpClass(cls):
734 cls.create_test_user = True
735 super(RgwUserQuotaTest, cls).setUpClass()
736
737 def _assert_quota(self, data):
738 self.assertIn('user_quota', data)
739 self.assertIn('max_objects', data['user_quota'])
740 self.assertIn('enabled', data['user_quota'])
741 self.assertIn('max_size_kb', data['user_quota'])
742 self.assertIn('max_size', data['user_quota'])
743 self.assertIn('bucket_quota', data)
744 self.assertIn('max_objects', data['bucket_quota'])
745 self.assertIn('enabled', data['bucket_quota'])
746 self.assertIn('max_size_kb', data['bucket_quota'])
747 self.assertIn('max_size', data['bucket_quota'])
748
749 def test_get_quota(self):
750 data = self._get('/api/rgw/user/teuth-test-user/quota')
751 self.assertStatus(200)
752 self._assert_quota(data)
753
754 def test_set_user_quota(self):
755 self._put(
756 '/api/rgw/user/teuth-test-user/quota',
757 params={
758 'quota_type': 'user',
759 'enabled': 'true',
760 'max_size_kb': 2048,
761 'max_objects': 101
762 })
763 self.assertStatus(200)
764
765 data = self._get('/api/rgw/user/teuth-test-user/quota')
766 self.assertStatus(200)
767 self._assert_quota(data)
768 self.assertEqual(data['user_quota']['max_objects'], 101)
769 self.assertTrue(data['user_quota']['enabled'])
770 self.assertEqual(data['user_quota']['max_size_kb'], 2048)
771
772 def test_set_bucket_quota(self):
773 self._put(
774 '/api/rgw/user/teuth-test-user/quota',
775 params={
776 'quota_type': 'bucket',
777 'enabled': 'false',
778 'max_size_kb': 4096,
779 'max_objects': 2000
780 })
781 self.assertStatus(200)
782
783 data = self._get('/api/rgw/user/teuth-test-user/quota')
784 self.assertStatus(200)
785 self._assert_quota(data)
786 self.assertEqual(data['bucket_quota']['max_objects'], 2000)
787 self.assertFalse(data['bucket_quota']['enabled'])
788 self.assertEqual(data['bucket_quota']['max_size_kb'], 4096)
789
790
791class RgwUserSubuserTest(RgwTestCase):
792
793 AUTH_ROLES = ['rgw-manager']
794
795 @classmethod
796 def setUpClass(cls):
797 cls.create_test_user = True
798 super(RgwUserSubuserTest, cls).setUpClass()
799
800 def test_create_swift(self):
801 self._post(
802 '/api/rgw/user/teuth-test-user/subuser',
803 params={
804 'subuser': 'tux',
805 'access': 'readwrite',
806 'key_type': 'swift'
807 })
39ae355f 808 self.assertStatus(200)
11fdf7f2
TL
809 data = self.jsonBody()
810 subuser = self.find_object_in_list('id', 'teuth-test-user:tux', data)
811 self.assertIsInstance(subuser, object)
812 self.assertEqual(subuser['permissions'], 'read-write')
813
814 # Get the user data to validate the keys.
815 data = self.get_rgw_user('teuth-test-user')
816 self.assertStatus(200)
817 key = self.find_object_in_list('user', 'teuth-test-user:tux',
818 data['swift_keys'])
819 self.assertIsInstance(key, object)
820
821 def test_create_s3(self):
822 self._post(
823 '/api/rgw/user/teuth-test-user/subuser',
824 params={
825 'subuser': 'hugo',
826 'access': 'write',
827 'generate_secret': 'false',
828 'access_key': 'yyy',
829 'secret_key': 'xxx'
830 })
39ae355f 831 self.assertStatus(200)
11fdf7f2
TL
832 data = self.jsonBody()
833 subuser = self.find_object_in_list('id', 'teuth-test-user:hugo', data)
834 self.assertIsInstance(subuser, object)
835 self.assertEqual(subuser['permissions'], 'write')
836
837 # Get the user data to validate the keys.
838 data = self.get_rgw_user('teuth-test-user')
839 self.assertStatus(200)
840 key = self.find_object_in_list('user', 'teuth-test-user:hugo',
841 data['keys'])
842 self.assertIsInstance(key, object)
843 self.assertEqual(key['secret_key'], 'xxx')
844
845 def test_delete_w_purge(self):
846 self._delete(
847 '/api/rgw/user/teuth-test-user/subuser/teuth-test-subuser2')
848 self.assertStatus(204)
849
850 # Get the user data to check that the keys don't exist anymore.
851 data = self.get_rgw_user('teuth-test-user')
852 self.assertStatus(200)
853 key = self.find_object_in_list(
854 'user', 'teuth-test-user:teuth-test-subuser2', data['swift_keys'])
855 self.assertIsNone(key)
856
857 def test_delete_wo_purge(self):
858 self._delete(
859 '/api/rgw/user/teuth-test-user/subuser/teuth-test-subuser',
860 params={'purge_keys': 'false'})
861 self.assertStatus(204)
862
863 # Get the user data to check whether they keys still exist.
864 data = self.get_rgw_user('teuth-test-user')
865 self.assertStatus(200)
866 key = self.find_object_in_list(
867 'user', 'teuth-test-user:teuth-test-subuser', data['keys'])
868 self.assertIsInstance(key, object)