]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard: support setting password hashes
authorFabian Bonk <fabian.bonk@croit.io>
Fri, 19 Jul 2019 14:31:20 +0000 (16:31 +0200)
committerFabian Bonk <fabian.bonk@croit.io>
Tue, 23 Jul 2019 09:33:15 +0000 (11:33 +0200)
Signed-off-by: Fabian Bonk <fabian.bonk@croit.io>
doc/mgr/dashboard.rst
src/pybind/mgr/dashboard/services/access_control.py
src/pybind/mgr/dashboard/tests/test_access_control.py

index 86e62e854db651d24b467ac8bf972b3b3d0a55d2..8c2ba4a53401b15a6c32b91de4423cbd47c3a8e1 100644 (file)
@@ -619,6 +619,13 @@ We provide a set of CLI commands to manage user accounts:
 
   $ ceph dashboard ac-user-set-password <username> <password>
 
+- *Change Password Hash*::
+
+  $ ceph dashboard ac-user-set-password-hash <username> <hash>
+
+  The hash must be a bcrypt hash and salt, e.g. ``$2b$12$Pt3Vq/rDt2y9glTPSV.VFegiLkQeIpddtkhoFetNApYmIJOY8gau2``.
+  This can be used to import users from an external database.
+
 - *Modify User (name, and email)*::
 
   $ ceph dashboard ac-user-set-info <username> <name> <email>
index 2fb873479c1119c8af2d6300b93c80bad6d1d9ee..6c7e58c83c1634318b54f56ad9f44b10707f24db 100644 (file)
@@ -186,7 +186,10 @@ class User(object):
         self.lastUpdate = int(time.time())
 
     def set_password(self, password):
-        self.password = password_hash(password)
+        self.set_password_hash(password_hash(password))
+
+    def set_password_hash(self, hashed_password):
+        self.password = hashed_password
         self.refreshLastUpdate()
 
     def compare_password(self, password):
@@ -632,6 +635,25 @@ def ac_user_set_password(_, username, password):
         return -errno.ENOENT, '', str(ex)
 
 
+@CLIWriteCommand('dashboard ac-user-set-password-hash',
+                 'name=username,type=CephString '
+                 'name=hashed_password,type=CephString',
+                 'Set user password bcrypt hash')
+def ac_user_set_password_hash(_, username, hashed_password):
+    try:
+        # make sure the hashed_password is actually a bcrypt hash
+        bcrypt.checkpw(b'', hashed_password.encode('utf-8'))
+        user = mgr.ACCESS_CTRL_DB.get_user(username)
+        user.set_password_hash(hashed_password)
+
+        mgr.ACCESS_CTRL_DB.save()
+        return 0, json.dumps(user.to_dict()), ''
+    except ValueError:
+        return -errno.EINVAL, '', 'Invalid password hash'
+    except UserDoesNotExist as ex:
+        return -errno.ENOENT, '', str(ex)
+
+
 @CLIWriteCommand('dashboard ac-user-set-info',
                  'name=username,type=CephString '
                  'name=name,type=CephString '
index 68bdaf1aa79f70b600b9f8023d9287d3b3f951b6..955f71bd22f51329d18a389b7fa2887d2db152a0 100644 (file)
@@ -562,6 +562,42 @@ class AccessControlTest(unittest.TestCase, CLICommandTestMixin):
         self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
         self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
 
+    def test_set_user_password_hash(self):
+        user_orig = self.test_create_user()
+        user = self.exec_cmd('ac-user-set-password-hash', username='admin',
+                             hashed_password='$2b$12$Pt3Vq/rDt2y9glTPSV.'
+                                             'VFegiLkQeIpddtkhoFetNApYmIJOY8gau2')
+        pass_hash = password_hash('newpass', user['password'])
+        self.assertDictEqual(user, {
+            'username': 'admin',
+            'password': pass_hash,
+            'name': 'admin User',
+            'email': 'admin@user.com',
+            'lastUpdate': user['lastUpdate'],
+            'roles': []
+        })
+        self.validate_persistent_user('admin', [], pass_hash, 'admin User',
+                                      'admin@user.com')
+        self.assertGreaterEqual(user['lastUpdate'], user_orig['lastUpdate'])
+
+    def test_set_user_password_hash_nonexistent_user(self):
+        with self.assertRaises(CmdException) as ctx:
+            self.exec_cmd('ac-user-set-password-hash', username='admin',
+                          hashed_password='$2b$12$Pt3Vq/rDt2y9glTPSV.'
+                                          'VFegiLkQeIpddtkhoFetNApYmIJOY8gau2')
+
+        self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+        self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+    def test_set_user_password_hash_broken_hash(self):
+        self.test_create_user()
+        with self.assertRaises(CmdException) as ctx:
+            self.exec_cmd('ac-user-set-password-hash', username='admin',
+                          hashed_password='')
+
+        self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
+        self.assertEqual(str(ctx.exception), 'Invalid password hash')
+
     def test_set_login_credentials(self):
         self.exec_cmd('set-login-credentials', username='admin',
                       password='admin')