]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/mgr/dashboard/test_user.py
1 # -*- coding: utf-8 -*-
3 from __future__
import absolute_import
7 from datetime
import datetime
, timedelta
9 from tasks
.mgr
.dashboard
.helper
import DashboardTestCase
, JObj
, JLeaf
12 class UserTest(DashboardTestCase
):
15 super(UserTest
, cls
).setUpClass()
16 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-enabled', 'true'])
17 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-length-enabled', 'true'])
18 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-oldpwd-enabled', 'true'])
19 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-username-enabled', 'true'])
20 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-exclusion-list-enabled', 'true'])
21 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-complexity-enabled', 'true'])
22 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-sequential-chars-enabled', 'true'])
23 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-repetitive-chars-enabled', 'true'])
26 def tearDownClass(cls
):
27 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-username-enabled', 'false'])
28 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-exclusion-list-enabled', 'false'])
29 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-complexity-enabled', 'false'])
30 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-sequential-chars-enabled', 'false'])
31 cls
._ceph
_cmd
(['dashboard', 'set-pwd-policy-check-repetitive-chars-enabled', 'false'])
32 super(UserTest
, cls
).tearDownClass()
35 def _create_user(cls
, username
=None, password
=None, name
=None, email
=None, roles
=None,
36 enabled
=True, pwd_expiration_date
=None, pwd_update_required
=False):
39 data
['username'] = username
41 data
['password'] = password
48 if pwd_expiration_date
:
49 data
['pwdExpirationDate'] = pwd_expiration_date
50 data
['pwdUpdateRequired'] = pwd_update_required
51 data
['enabled'] = enabled
52 cls
._post
("/api/user", data
)
55 def _reset_login_to_admin(cls
, username
=None):
58 cls
.delete_user(username
)
59 cls
.login('admin', 'admin')
61 def test_crud_user(self
):
62 self
._create
_user
(username
='user1',
63 password
='mypassword10#',
66 roles
=['administrator'])
67 self
.assertStatus(201)
68 user
= self
.jsonBody()
70 self
._get
('/api/user/user1')
71 self
.assertStatus(200)
75 'email': 'my@email.com',
76 'roles': ['administrator'],
77 'lastUpdate': user
['lastUpdate'],
79 'pwdExpirationDate': None,
80 'pwdUpdateRequired': False
83 self
._put
('/api/user/user1', {
84 'name': 'My New Name',
85 'email': 'mynew@email.com',
86 'roles': ['block-manager'],
88 self
.assertStatus(200)
89 user
= self
.jsonBody()
92 'name': 'My New Name',
93 'email': 'mynew@email.com',
94 'roles': ['block-manager'],
95 'lastUpdate': user
['lastUpdate'],
97 'pwdExpirationDate': None,
98 'pwdUpdateRequired': False
101 self
._delete
('/api/user/user1')
102 self
.assertStatus(204)
104 def test_crd_disabled_user(self
):
105 self
._create
_user
(username
='klara',
106 password
='mypassword10#',
107 name
='Klara Musterfrau',
108 email
='klara@musterfrau.com',
109 roles
=['administrator'],
111 self
.assertStatus(201)
112 user
= self
.jsonBody()
114 # Restart dashboard module.
115 self
._unload
_module
('dashboard')
116 self
._load
_module
('dashboard')
119 self
._get
('/api/user/klara')
120 self
.assertStatus(200)
121 self
.assertJsonBody({
123 'name': 'Klara Musterfrau',
124 'email': 'klara@musterfrau.com',
125 'roles': ['administrator'],
126 'lastUpdate': user
['lastUpdate'],
128 'pwdExpirationDate': None,
129 'pwdUpdateRequired': False
132 self
._delete
('/api/user/klara')
133 self
.assertStatus(204)
135 def test_list_users(self
):
136 self
._get
('/api/user')
137 self
.assertStatus(200)
138 user
= self
.jsonBody()
139 self
.assertEqual(len(user
), 1)
141 self
.assertJsonBody([{
145 'roles': ['administrator'],
146 'lastUpdate': user
['lastUpdate'],
148 'pwdExpirationDate': None,
149 'pwdUpdateRequired': False
152 def test_create_user_already_exists(self
):
153 self
._create
_user
(username
='admin',
154 password
='mypassword10#',
155 name
='administrator',
156 email
='my@email.com',
157 roles
=['administrator'])
158 self
.assertStatus(400)
159 self
.assertError(code
='username_already_exists',
162 def test_create_user_invalid_role(self
):
163 self
._create
_user
(username
='user1',
164 password
='mypassword10#',
166 email
='my@email.com',
167 roles
=['invalid-role'])
168 self
.assertStatus(400)
169 self
.assertError(code
='role_does_not_exist',
172 def test_delete_user_does_not_exist(self
):
173 self
._delete
('/api/user/user2')
174 self
.assertStatus(404)
176 @DashboardTestCase.RunAs('test', 'test', [{'user': ['create', 'read', 'update', 'delete']}])
177 def test_delete_current_user(self
):
178 self
._delete
('/api/user/test')
179 self
.assertStatus(400)
180 self
.assertError(code
='cannot_delete_current_user',
183 @DashboardTestCase.RunAs('test', 'test', [{'user': ['create', 'read', 'update', 'delete']}])
184 def test_disable_current_user(self
):
185 self
._put
('/api/user/test', {'enabled': False})
186 self
.assertStatus(400)
187 self
.assertError(code
='cannot_disable_current_user',
190 def test_update_user_does_not_exist(self
):
191 self
._put
('/api/user/user2', {'name': 'My New Name'})
192 self
.assertStatus(404)
194 def test_update_user_invalid_role(self
):
195 self
._put
('/api/user/admin', {'roles': ['invalid-role']})
196 self
.assertStatus(400)
197 self
.assertError(code
='role_does_not_exist',
200 def test_change_password_from_other_user(self
):
201 self
._post
('/api/user/test2/change_password', {
202 'old_password': 'abc',
203 'new_password': 'xyz'
205 self
.assertStatus(400)
206 self
.assertError(code
='invalid_user_context', component
='user')
208 def test_change_password_old_not_match(self
):
209 self
._post
('/api/user/admin/change_password', {
210 'old_password': 'foo',
211 'new_password': 'bar'
213 self
.assertStatus(400)
214 self
.assertError(code
='invalid_old_password', component
='user')
216 def test_change_password_as_old_password(self
):
217 self
.create_user('test1', 'mypassword10#', ['read-only'], force_password
=False)
218 self
.login('test1', 'mypassword10#')
219 self
._post
('/api/user/test1/change_password', {
220 'old_password': 'mypassword10#',
221 'new_password': 'mypassword10#'
223 self
.assertStatus(400)
224 self
.assertError('password_policy_validation_failed', 'user',
225 'Password must not be the same as the previous one.')
226 self
._reset
_login
_to
_admin
('test1')
228 def test_change_password_contains_username(self
):
229 self
.create_user('test1', 'mypassword10#', ['read-only'], force_password
=False)
230 self
.login('test1', 'mypassword10#')
231 self
._post
('/api/user/test1/change_password', {
232 'old_password': 'mypassword10#',
233 'new_password': 'mypasstest1@#'
235 self
.assertStatus(400)
236 self
.assertError('password_policy_validation_failed', 'user',
237 'Password must not contain username.')
238 self
._reset
_login
_to
_admin
('test1')
240 def test_change_password_contains_forbidden_words(self
):
241 self
.create_user('test1', 'mypassword10#', ['read-only'], force_password
=False)
242 self
.login('test1', 'mypassword10#')
243 self
._post
('/api/user/test1/change_password', {
244 'old_password': 'mypassword10#',
245 'new_password': 'mypassOSD01'
247 self
.assertStatus(400)
248 self
.assertError('password_policy_validation_failed', 'user',
249 'Password must not contain the keyword "OSD".')
250 self
._reset
_login
_to
_admin
('test1')
252 def test_change_password_contains_sequential_characters(self
):
253 self
.create_user('test1', 'mypassword10#', ['read-only'], force_password
=False)
254 self
.login('test1', 'mypassword10#')
255 self
._post
('/api/user/test1/change_password', {
256 'old_password': 'mypassword10#',
257 'new_password': 'mypass123456!@$'
259 self
.assertStatus(400)
260 self
.assertError('password_policy_validation_failed', 'user',
261 'Password must not contain sequential characters.')
262 self
._reset
_login
_to
_admin
('test1')
264 def test_change_password_contains_repetetive_characters(self
):
265 self
.create_user('test1', 'mypassword10#', ['read-only'], force_password
=False)
266 self
.login('test1', 'mypassword10#')
267 self
._post
('/api/user/test1/change_password', {
268 'old_password': 'mypassword10#',
269 'new_password': 'aaaaA1@!#'
271 self
.assertStatus(400)
272 self
.assertError('password_policy_validation_failed', 'user',
273 'Password must not contain repetitive characters.')
274 self
._reset
_login
_to
_admin
('test1')
276 @DashboardTestCase.RunAs('test1', 'mypassword10#', ['read-only'], False)
277 def test_change_password(self
):
278 self
._post
('/api/user/test1/change_password', {
279 'old_password': 'mypassword10#',
280 'new_password': 'newpassword01#'
282 self
.assertStatus(200)
284 self
._post
('/api/auth', {'username': 'test1', 'password': 'mypassword10#'})
285 self
.assertStatus(400)
286 self
.assertError(code
='invalid_credentials', component
='auth')
288 def test_create_user_password_cli(self
):
289 exitcode
= self
._ceph
_cmd
_result
(['dashboard', 'ac-user-create',
290 'test1', 'mypassword10#'])
291 self
.assertEqual(exitcode
, 0)
292 self
.delete_user('test1')
294 @DashboardTestCase.RunAs('test2', 'foo_bar_10#', force_password
=False, login
=False)
295 def test_change_user_password_cli(self
):
296 exitcode
= self
._ceph
_cmd
_result
(['dashboard', 'ac-user-set-password',
297 'test2', 'foo_new-password01#'])
298 self
.assertEqual(exitcode
, 0)
300 def test_create_user_password_force_cli(self
):
301 exitcode
= self
._ceph
_cmd
_result
(['dashboard', 'ac-user-create',
302 '--force-password', 'test11',
304 self
.assertEqual(exitcode
, 0)
305 self
.delete_user('test11')
307 @DashboardTestCase.RunAs('test22', 'foo_bar_10#', force_password
=False, login
=False)
308 def test_change_user_password_force_cli(self
):
309 exitcode
= self
._ceph
_cmd
_result
(['dashboard', 'ac-user-set-password',
310 '--force-password', 'test22',
312 self
.assertEqual(exitcode
, 0)
314 def test_create_user_password_cli_fail(self
):
315 exitcode
= self
._ceph
_cmd
_result
(['dashboard', 'ac-user-create', 'test3', 'foo'])
316 self
.assertNotEqual(exitcode
, 0)
318 @DashboardTestCase.RunAs('test4', 'x1z_tst+_10#', force_password
=False, login
=False)
319 def test_change_user_password_cli_fail(self
):
320 exitcode
= self
._ceph
_cmd
_result
(['dashboard', 'ac-user-set-password',
322 self
.assertNotEqual(exitcode
, 0)
324 def test_create_user_with_pwd_expiration_date(self
):
325 future_date
= datetime
.utcnow() + timedelta(days
=10)
326 future_date
= int(time
.mktime(future_date
.timetuple()))
328 self
._create
_user
(username
='user1',
329 password
='mypassword10#',
331 email
='my@email.com',
332 roles
=['administrator'],
333 pwd_expiration_date
=future_date
)
334 self
.assertStatus(201)
335 user
= self
.jsonBody()
337 self
._get
('/api/user/user1')
338 self
.assertStatus(200)
339 self
.assertJsonBody({
342 'email': 'my@email.com',
343 'roles': ['administrator'],
344 'lastUpdate': user
['lastUpdate'],
346 'pwdExpirationDate': future_date
,
347 'pwdUpdateRequired': False
349 self
._delete
('/api/user/user1')
351 def test_create_with_pwd_expiration_date_not_valid(self
):
352 past_date
= datetime
.utcnow() - timedelta(days
=10)
353 past_date
= int(time
.mktime(past_date
.timetuple()))
355 self
._create
_user
(username
='user1',
356 password
='mypassword10#',
358 email
='my@email.com',
359 roles
=['administrator'],
360 pwd_expiration_date
=past_date
)
361 self
.assertStatus(400)
362 self
.assertError(code
='pwd_past_expiration_date', component
='user')
364 def test_create_with_default_expiration_date(self
):
365 future_date_1
= datetime
.utcnow() + timedelta(days
=9)
366 future_date_1
= int(time
.mktime(future_date_1
.timetuple()))
367 future_date_2
= datetime
.utcnow() + timedelta(days
=11)
368 future_date_2
= int(time
.mktime(future_date_2
.timetuple()))
370 self
._ceph
_cmd
(['dashboard', 'set-user-pwd-expiration-span', '10'])
371 self
._create
_user
(username
='user1',
372 password
='mypassword10#',
374 email
='my@email.com',
375 roles
=['administrator'])
376 self
.assertStatus(201)
378 user
= self
._get
('/api/user/user1')
379 self
.assertStatus(200)
380 self
.assertIsNotNone(user
['pwdExpirationDate'])
381 self
.assertGreater(user
['pwdExpirationDate'], future_date_1
)
382 self
.assertLess(user
['pwdExpirationDate'], future_date_2
)
384 self
._delete
('/api/user/user1')
385 self
._ceph
_cmd
(['dashboard', 'set-user-pwd-expiration-span', '0'])
387 def test_pwd_expiration_date_update(self
):
388 self
._ceph
_cmd
(['dashboard', 'set-user-pwd-expiration-span', '10'])
389 self
.create_user('user1', 'mypassword10#', ['administrator'])
391 user_1
= self
._get
('/api/user/user1')
392 self
.assertStatus(200)
394 self
.login('user1', 'mypassword10#')
395 self
._post
('/api/user/user1/change_password', {
396 'old_password': 'mypassword10#',
397 'new_password': 'newpassword01#'
399 self
.assertStatus(200)
401 # Compare password expiration dates.
402 self
._reset
_login
_to
_admin
()
403 user_1_pwd_changed
= self
._get
('/api/user/user1')
404 self
.assertStatus(200)
405 self
.assertLess(user_1
['pwdExpirationDate'], user_1_pwd_changed
['pwdExpirationDate'])
408 self
.delete_user('user1')
409 self
._ceph
_cmd
(['dashboard', 'set-user-pwd-expiration-span', '0'])
411 def test_pwd_update_required(self
):
412 self
._create
_user
(username
='user1',
413 password
='mypassword10#',
415 email
='my@email.com',
416 roles
=['administrator'],
417 pwd_update_required
=True)
418 self
.assertStatus(201)
420 user_1
= self
._get
('/api/user/user1')
421 self
.assertStatus(200)
422 self
.assertEqual(user_1
['pwdUpdateRequired'], True)
424 self
.login('user1', 'mypassword10#')
425 self
.assertStatus(201)
427 self
._get
('/api/osd')
428 self
.assertStatus(403)
429 self
._reset
_login
_to
_admin
('user1')
431 def test_pwd_update_required_change_pwd(self
):
432 self
._create
_user
(username
='user1',
433 password
='mypassword10#',
435 email
='my@email.com',
436 roles
=['administrator'],
437 pwd_update_required
=True)
438 self
.assertStatus(201)
440 self
.login('user1', 'mypassword10#')
441 self
._post
('/api/user/user1/change_password', {
442 'old_password': 'mypassword10#',
443 'new_password': 'newpassword01#'
446 self
.login('user1', 'newpassword01#')
447 user_1
= self
._get
('/api/user/user1')
448 self
.assertStatus(200)
449 self
.assertEqual(user_1
['pwdUpdateRequired'], False)
450 self
._get
('/api/osd')
451 self
.assertStatus(200)
452 self
._reset
_login
_to
_admin
('user1')
454 def test_validate_password_weak(self
):
455 self
._post
('/api/user/validate_password', {
456 'password': 'mypassword1'
458 self
.assertStatus(200)
459 self
.assertJsonBody({
465 def test_validate_password_ok(self
):
466 self
._post
('/api/user/validate_password', {
467 'password': 'mypassword1!@'
469 self
.assertStatus(200)
470 self
.assertJsonBody({
476 def test_validate_password_strong(self
):
477 self
._post
('/api/user/validate_password', {
478 'password': 'testpassword0047!@'
480 self
.assertStatus(200)
481 self
.assertJsonBody({
484 'valuation': 'Strong'
487 def test_validate_password_very_strong(self
):
488 self
._post
('/api/user/validate_password', {
489 'password': 'testpassword#!$!@$'
491 self
.assertStatus(200)
492 self
.assertJsonBody({
495 'valuation': 'Very strong'
498 def test_validate_password_fail(self
):
499 self
._post
('/api/user/validate_password', {
502 self
.assertStatus(200)
503 self
.assertJsonBody({
506 'valuation': 'Password is too weak.'
509 def test_validate_password_fail_name(self
):
510 self
._post
('/api/user/validate_password', {
511 'password': 'x1zhugo_10',
514 self
.assertStatus(200)
515 self
.assertJsonBody({
518 'valuation': 'Password must not contain username.'
521 def test_validate_password_fail_oldpwd(self
):
522 self
._post
('/api/user/validate_password', {
523 'password': 'x1zt-st10',
524 'old_password': 'x1zt-st10'
526 self
.assertStatus(200)
527 self
.assertJsonBody({
530 'valuation': 'Password must not be the same as the previous one.'
533 def test_create_user_pwd_update_required(self
):
534 self
.create_user('foo', 'bar', cmd_args
=['--pwd_update_required'])
535 self
._get
('/api/user/foo')
536 self
.assertStatus(200)
537 self
.assertJsonSubset({
539 'pwdUpdateRequired': True
541 self
.delete_user('foo')