From 952d15827b9a299e6a13a8f0e3a0f3b0c36118cc Mon Sep 17 00:00:00 2001
From: Gleb Kashkin <g.kashkin@tarantool.org>
Date: Wed, 11 Oct 2023 10:07:45 +0000
Subject: [PATCH] config: update password hashes after auth_type change

User password is stored in a system space is a form of hash when
'chap-sha1' auth type is set, and in a form of hash with salt when
'pap-sha256' is set.

Now, if a user is set inside config, and the current auth type is
different from the type the users password is stored in, the password
hash will be regenerated.

Part of #8967

NO_DOC=documentation request will be filed manually for the whole
       credentials
---
 .../gh-8967-creds-consider-auth-type.md       |  5 ++
 src/box/lua/config/applier/credentials.lua    | 33 ++++++++-----
 .../credentials_applier_test.lua              | 49 +++++++++++++++++++
 3 files changed, 76 insertions(+), 11 deletions(-)
 create mode 100644 changelogs/unreleased/gh-8967-creds-consider-auth-type.md

diff --git a/changelogs/unreleased/gh-8967-creds-consider-auth-type.md b/changelogs/unreleased/gh-8967-creds-consider-auth-type.md
new file mode 100644
index 0000000000..a91a7707d2
--- /dev/null
+++ b/changelogs/unreleased/gh-8967-creds-consider-auth-type.md
@@ -0,0 +1,5 @@
+## feature/config
+
+* Now a password hash (and salt) will be regenerated for users managed
+  in the configuration file if `security.auth_type` differs from a user's
+  `auth_type` (gh-8967).
diff --git a/src/box/lua/config/applier/credentials.lua b/src/box/lua/config/applier/credentials.lua
index 5723fea63e..6e088f412c 100644
--- a/src/box/lua/config/applier/credentials.lua
+++ b/src/box/lua/config/applier/credentials.lua
@@ -632,17 +632,14 @@ local function set_password(user_name, password)
 
     local auth_type = auth_def['chap-sha1'] and 'chap-sha1' or 'pap-sha256'
 
+    local new_password = false
+
     if auth_type == 'chap-sha1' then
         local current_hash = auth_def['chap-sha1']
 
         local new_hash = box.schema.user.password(password)
-        if new_hash == current_hash then
-            log.verbose('credentials.apply: a password is already set ' ..
-                        'for user %q', user_name)
-        else
-            log.verbose('credentials.apply: set a password for user %q',
-                        user_name)
-            box.schema.user.passwd(user_name, password)
+        if new_hash ~= current_hash then
+            new_password = true
         end
     else
         assert(auth_def['pap-sha256'])
@@ -651,16 +648,30 @@ local function set_password(user_name, password)
 
         local new_hash = digest.sha256(current_salt .. password)
         if new_hash == current_hash then
+            -- Note: passwd() generated new random salt, it will be different
+            -- from current_salt.
+            new_password = true
+        end
+    end
+
+    if not new_password then
+        -- Note that security.auth_type is applied by box_cfg applier.
+        -- It is executed before credentials applier, so the current
+        -- box.cfg.auth_type is already set.
+        if box.cfg.auth_type == auth_type then
             log.verbose('credentials.apply: a password is already set ' ..
                         'for user %q', user_name)
         else
-            log.verbose('credentials.apply: set a password for user %q',
-                        user_name)
-            -- Note: passwd() generated new random salt, it will be different
-            -- from current_salt.
+            log.verbose('credentials.apply: a password for user %q has ' ..
+                        'different auth_type, resetting it', user_name)
             box.schema.user.passwd(user_name, password)
         end
+    else
+        log.verbose('credentials.apply: set a password for user %q',
+                    user_name)
+        box.schema.user.passwd(user_name, password)
     end
+
 end
 
 local function create_users(user_map)
diff --git a/test/config-luatest/credentials_applier_test.lua b/test/config-luatest/credentials_applier_test.lua
index 5a91a0d2bf..e5e76322d1 100644
--- a/test/config-luatest/credentials_applier_test.lua
+++ b/test/config-luatest/credentials_applier_test.lua
@@ -1296,3 +1296,52 @@ g.test_lua_eval_lua_call_sql = function()
         end
     })
 end
+
+g.test_consider_auth_type_for_passwods = function(g)
+    t.tarantool.skip_if_not_enterprise()
+
+    helpers.reload_success_case(g, {
+        options = {
+            credentials = {
+                users = {
+                    guest = {
+                        roles = { 'super' }
+                    },
+                    myuser = {
+                        password = 'secret',
+                    },
+                },
+            },
+            security = {
+                auth_type = 'chap-sha1',
+            },
+        },
+        verify = function()
+            t.assert_equals(box.cfg.auth_type, 'chap-sha1')
+
+            local password_def = box.space._user.index.name:get({'myuser'})[5]
+            t.assert_equals(type(password_def['chap-sha1']), 'string')
+        end,
+        options_2 = {
+            credentials = {
+                users = {
+                    guest = {
+                        roles = { 'super' }
+                    },
+                    myuser = {
+                        password = 'secret',
+                    },
+                },
+            },
+            security = {
+                auth_type = 'pap-sha256',
+            },
+        },
+        verify_2 = function()
+            t.assert_equals(box.cfg.auth_type, 'pap-sha256')
+
+            local password_def = box.space._user.index.name:get({'myuser'})[5]
+            t.assert_equals(type(password_def['pap-sha256']), 'table')
+        end,
+    })
+end
-- 
GitLab