From e8abd58b6b4a48454c2e7fcb18d05a6181e71c67 Mon Sep 17 00:00:00 2001
From: Vartan Babayan <v.babayan@picodata.io>
Date: Fri, 6 Sep 2024 17:06:14 +0400
Subject: [PATCH] feat: use md5 auth by default

---
 CHANGELOG.md                    |  4 +-
 sbroad                          |  2 +-
 src/access_control.rs           |  4 +-
 src/bootstrap_entries.rs        | 26 +++++++++++-
 src/cli/args.rs                 | 11 ++++-
 src/cli/expel.rs                |  2 +-
 src/schema.rs                   | 17 ++++----
 test/conftest.py                | 17 +++++---
 test/int/test_access_control.py |  8 ++--
 test/int/test_acl.py            | 17 ++++----
 test/int/test_audit.py          |  8 ++--
 test/int/test_basics.py         |  5 ++-
 test/int/test_cli_connect.py    | 46 ++++++++++++++++++--
 test/int/test_ddl.py            | 74 ++++++++++++++++-----------------
 test/int/test_gostech_audit.py  |  6 ++-
 test/int/test_sql.py            | 27 +++++++-----
 test/pgproto/auth_test.py       | 37 ++++++++++++++++-
 test/pgproto/types_test.py      |  8 ++--
 18 files changed, 222 insertions(+), 97 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e8ecada3c..939968285a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,11 +18,13 @@ with the `YY.MINOR.MICRO` scheme.
 
 - Order of columns in `_pico_service_route` table has changed.
 
+- Default authorization method changed from chap-sha to md5 both for user creation and in connect CLI.
+
 - Support human numbers to configure memtx.memory
   Supported suffixes: K, M, G, T, 1K = 1024
   (e.g picodata run --memtx-memory 10G)
 
-- - Replace the use of `localhost` with `127.0.0.1` in `picodata run --listen` default value
+- Replace the use of `localhost` with `127.0.0.1` in `picodata run --listen` default value
     and everywhere across documentation and examples to reduce ambiguity.
 
 - New rpc entrypoint: `.proc_get_vshard_config` which returns the vshard configuration of tier.
diff --git a/sbroad b/sbroad
index 97d2b81478..c87bf3d8d4 160000
--- a/sbroad
+++ b/sbroad
@@ -1 +1 @@
-Subproject commit 97d2b81478414c154cfa10c30c303f5ce0c8e0b7
+Subproject commit c87bf3d8d4feaed22018a20413dfbcddff42e4a9
diff --git a/src/access_control.rs b/src/access_control.rs
index ad9cd17ecc..e1d4703838 100644
--- a/src/access_control.rs
+++ b/src/access_control.rs
@@ -743,8 +743,8 @@ mod tests {
 
     fn dummy_auth_def() -> AuthDef {
         AuthDef::new(
-            AuthMethod::ChapSha1,
-            AuthData::new(&AuthMethod::ChapSha1, "", "").into_string(),
+            AuthMethod::Md5,
+            AuthData::new(&AuthMethod::Md5, "", "").into_string(),
         )
     }
 
diff --git a/src/bootstrap_entries.rs b/src/bootstrap_entries.rs
index a976862a41..324aaa8226 100644
--- a/src/bootstrap_entries.rs
+++ b/src/bootstrap_entries.rs
@@ -8,7 +8,7 @@ use crate::config::PicodataConfig;
 use crate::instance::Instance;
 use crate::replicaset::Replicaset;
 use crate::schema;
-use crate::schema::ADMIN_ID;
+use crate::schema::{ADMIN_ID, GUEST_ID};
 use crate::storage;
 use crate::storage::PropertyName;
 use crate::storage::{Clusterwide, ClusterwideTable};
@@ -282,7 +282,7 @@ pub(super) fn prepare(
             ))
         })?;
 
-        let method = AuthMethod::ChapSha1;
+        let method = AuthMethod::Md5;
         let name = "admin";
         validate_password(&password, &method, storage)?;
         let data = AuthData::new(&method, name, &password);
@@ -309,6 +309,28 @@ pub(super) fn prepare(
         tlog!(Info, "Password for user=admin has been set successfully");
     }
 
+    let op_elem = op::Op::Acl(op::Acl::ChangeAuth {
+        user_id: GUEST_ID,
+        auth: AuthDef::new(
+            AuthMethod::Md5,
+            AuthData::new(&AuthMethod::Md5, "guest", "").into_string(),
+        ),
+        initiator: ADMIN_ID,
+        schema_version: 1,
+    });
+
+    let context = traft::EntryContext::Op(op_elem);
+    init_entries.push(
+        traft::Entry {
+            entry_type: raft::EntryType::EntryNormal,
+            index: (init_entries.len() + 1) as _,
+            term: traft::INIT_RAFT_TERM,
+            data: vec![],
+            context,
+        }
+        .into(),
+    );
+
     //
     // Populate "_pico_table" & "_pico_index" with definitions of builtins
     //
diff --git a/src/cli/args.rs b/src/cli/args.rs
index a86d871ffd..1cf78ca5fc 100644
--- a/src/cli/args.rs
+++ b/src/cli/args.rs
@@ -369,6 +369,15 @@ pub struct Expel {
     /// Path to a plain-text file with the `admin` password.
     /// If this option isn't provided, the password is prompted from the terminal.
     pub password_file: Option<String>,
+
+    #[clap(
+        short = 'a',
+        long = "auth-type",
+        value_name = "METHOD",
+        default_value = AuthMethod::Md5.as_str(),
+    )]
+    /// The preferred authentication method.
+    pub auth_method: AuthMethod,
 }
 
 impl Expel {
@@ -454,7 +463,7 @@ pub struct Connect {
         short = 'a',
         long = "auth-type",
         value_name = "METHOD",
-        default_value = AuthMethod::ChapSha1.as_str(),
+        default_value = AuthMethod::Md5.as_str(),
     )]
     /// The preferred authentication method.
     pub auth_method: AuthMethod,
diff --git a/src/cli/expel.rs b/src/cli/expel.rs
index 002ad97ec5..bb80361a1d 100644
--- a/src/cli/expel.rs
+++ b/src/cli/expel.rs
@@ -12,7 +12,7 @@ pub async fn tt_expel(args: args::Expel) -> Result<(), Error> {
         &args.peer_address,
         Some("admin"),
         args.password_file.as_deref(),
-        tarantool::auth::AuthMethod::ChapSha1,
+        args.auth_method,
     )?;
 
     let req = ExpelRequest {
diff --git a/src/schema.rs b/src/schema.rs
index 9cccde3c45..cb2dd25814 100644
--- a/src/schema.rs
+++ b/src/schema.rs
@@ -848,10 +848,7 @@ impl UserDef {
             id: 69,
             name: "david".into(),
             schema_version: 421,
-            auth: Some(AuthDef::new(
-                tarantool::auth::AuthMethod::ChapSha1,
-                "".into(),
-            )),
+            auth: Some(AuthDef::new(AuthMethod::Md5, "".into())),
             owner: 42,
             ty: UserMetadataKind::User,
         }
@@ -1236,7 +1233,7 @@ pub fn system_user_definitions() -> Vec<(UserDef, Vec<PrivilegeDef>)> {
     //
     // User "guest"
     //
-    // equivalent SQL expression: CREATE USER 'guest' WITH PASSWORD '' USING chap-sha1
+    // equivalent SQL expression: CREATE USER 'guest' WITH PASSWORD '' USING md5
     {
         let user_def = UserDef {
             id: GUEST_ID,
@@ -1244,8 +1241,8 @@ pub fn system_user_definitions() -> Vec<(UserDef, Vec<PrivilegeDef>)> {
             // This means the local schema is already up to date and main loop doesn't need to do anything
             schema_version: INITIAL_SCHEMA_VERSION,
             auth: Some(AuthDef::new(
-                AuthMethod::ChapSha1,
-                AuthData::new(&AuthMethod::ChapSha1, DEFAULT_USERNAME, "").into_string(),
+                AuthMethod::Md5,
+                AuthData::new(&AuthMethod::Md5, DEFAULT_USERNAME, "").into_string(),
             )),
             owner: initiator,
             ty: UserMetadataKind::User,
@@ -1287,7 +1284,7 @@ pub fn system_user_definitions() -> Vec<(UserDef, Vec<PrivilegeDef>)> {
             // MP_MAP. Here for simplicity given available module api we
             // use ChapSha with invalid password (its impossible to get
             // empty string as output of sha1)
-            auth: Some(AuthDef::new(AuthMethod::ChapSha1, "".into())),
+            auth: Some(AuthDef::new(AuthMethod::Md5, "".into())),
             owner: initiator,
             ty: UserMetadataKind::User,
         };
@@ -1318,7 +1315,7 @@ pub fn system_user_definitions() -> Vec<(UserDef, Vec<PrivilegeDef>)> {
             schema_version: INITIAL_SCHEMA_VERSION,
             auth: Some(AuthDef::new(
                 AuthMethod::ChapSha1,
-                tarantool::auth::AuthData::new(
+                AuthData::new(
                     &AuthMethod::ChapSha1,
                     PICO_SERVICE_USER_NAME,
                     pico_service_password(),
@@ -2553,7 +2550,7 @@ mod tests {
                 id: ADMIN_ID,
                 name: String::from("admin"),
                 schema_version: 0,
-                auth: Some(AuthDef::new(AuthMethod::ChapSha1, String::from(""))),
+                auth: Some(AuthDef::new(AuthMethod::Md5, String::from(""))),
                 owner: ADMIN_ID,
                 ty: UserMetadataKind::User,
             })
diff --git a/test/conftest.py b/test/conftest.py
index 56f28ce34a..25adf0912d 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -835,14 +835,16 @@ class Instance:
         self,
         with_name: str,
         with_password: str,
+        with_auth: str | None = None,
         user: str | None = None,
         password: str | None = None,
         timeout: int | float = 10,
     ):
+        sql = f"CREATE USER\"{with_name}\" WITH PASSWORD '{with_password}'" + (
+            ("USING " + with_auth) if with_auth else ""
+        )
         self.sql(
-            f"""
-            CREATE USER "{with_name}" WITH PASSWORD '{with_password}' USING chap-sha1
-            """,
+            sql=sql,
             user=user,
             password=password,
             timeout=timeout,
@@ -1698,7 +1700,11 @@ class Cluster:
     def remove_data(self):
         shutil.rmtree(self.data_dir)
 
-    def expel(self, target: Instance, peer: Instance | None = None):
+    def expel(
+        self,
+        target: Instance,
+        peer: Instance | None = None,
+    ):
         peer = peer if peer else target
         assert self.service_password_file, "cannot expel without pico_service password"
         assert target.instance_id, "cannot expel without target instance_id"
@@ -1709,6 +1715,7 @@ class Cluster:
             "--peer", f"pico_service@{peer.listen}",
             "--cluster-id", target.cluster_id or "",
             "--password-file", self.service_password_file,
+            "--auth-type", "chap-sha1",
             target.instance_id,
         ]
         # fmt: on
@@ -2347,7 +2354,7 @@ instance:
 
 # Exists for debugging purposes only. When you're debugging a single test it is
 # simpler to configure wireshark (or other tools) for particular port.
-# Shouldnt be used when multiple tests are run (will result in address already in use errors)
+# Shouldn't be used when multiple tests are run (will result in address already in use errors)
 PG_LISTEN = os.getenv("PG_LISTEN")
 
 
diff --git a/test/int/test_access_control.py b/test/int/test_access_control.py
index c8b1e525dd..a22a3e0572 100644
--- a/test/int/test_access_control.py
+++ b/test/int/test_access_control.py
@@ -24,8 +24,8 @@ _3_SEC = 3
 
 def test_access_global_table(cluster: Cluster):
     (i1,) = cluster.deploy(instance_count=1)
-    i1.sql("""create user "alice" with password 'T0psecret'""")
-    i1.sql("""create user "bob" with password 'T0tallysecret'""")
+    i1.sql("""create user "alice" with password 'T0psecret' using chap-sha1""")
+    i1.sql("""create user "bob" with password 'T0tallysecret' using chap-sha1""")
 
     create_table_friends_of_peppa = """
         create table "friends_of_peppa" (
@@ -87,8 +87,8 @@ def test_access_global_table(cluster: Cluster):
 
 def test_access_sharded_table(cluster: Cluster):
     (i1,) = cluster.deploy(instance_count=1)
-    i1.sql("""create user "alice" with password 'T0psecret'""")
-    i1.sql("""create user "bob" with password 'T0tallysecret'""")
+    i1.sql("""create user "alice" with password 'T0psecret' using chap-sha1""")
+    i1.sql("""create user "bob" with password 'T0tallysecret' using chap-sha1""")
 
     create_table_wonderland = """
         create table "wonderland" (
diff --git a/test/int/test_acl.py b/test/int/test_acl.py
index db21aafaa6..a34b683053 100644
--- a/test/int/test_acl.py
+++ b/test/int/test_acl.py
@@ -93,7 +93,7 @@ def test_acl_basic(cluster: Cluster):
     i1, *_ = cluster.deploy(instance_count=4, init_replication_factor=2)
 
     user = "Bobby"
-    v = 0
+    v = 1
 
     # Initial state.
     for i in cluster.instances:
@@ -103,7 +103,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Create user.
-    i1.sql(f"CREATE USER \"{user}\" WITH PASSWORD '{VALID_PASSWORD}'")
+    i1.sql(f"CREATE USER \"{user}\" WITH PASSWORD '{VALID_PASSWORD}' using chap-sha1")
     index = i1.call(".proc_get_index")
     cluster.raft_wait_index(index)
     v += 1
@@ -209,7 +209,7 @@ def test_acl_basic(cluster: Cluster):
     # Change user's password.
     old_password = VALID_PASSWORD
     new_password = "L0ng$3kr3T"
-    i1.sql(f"ALTER USER \"{user}\" WITH PASSWORD '{new_password}'")
+    i1.sql(f"ALTER USER \"{user}\" WITH PASSWORD '{new_password}' using chap-sha1")
     index = i1.call(".proc_get_index")
     cluster.raft_wait_index(index)
     v += 1
@@ -263,7 +263,7 @@ def test_acl_roles_basic(cluster: Cluster):
     user = "Steven"
 
     # Create user.
-    i1.sql(f"CREATE USER \"{user}\" WITH PASSWORD '{VALID_PASSWORD}'")
+    i1.sql(f"CREATE USER \"{user}\" WITH PASSWORD '{VALID_PASSWORD}' using chap-sha1")
     index = i1.call(".proc_get_index")
     cluster.raft_wait_index(index)
 
@@ -343,7 +343,7 @@ def test_cas_permissions(cluster: Cluster):
     user = "Steven"
 
     # Create user.
-    i1.sql(f"CREATE USER \"{user}\" WITH PASSWORD '{VALID_PASSWORD}'")
+    i1.sql(f"CREATE USER \"{user}\" WITH PASSWORD '{VALID_PASSWORD}' using chap-sha1")
     index = i1.call(".proc_get_index")
     cluster.raft_wait_index(index)
 
@@ -561,7 +561,7 @@ def test_builtin_users_and_roles(cluster: Cluster):
 def test_create_table_smoke(cluster: Cluster):
     i1, *_ = cluster.deploy(instance_count=1)
 
-    i1.sql(f"CREATE USER \"Dave\" WITH PASSWORD '{VALID_PASSWORD}'")
+    i1.sql(f"CREATE USER \"Dave\" WITH PASSWORD '{VALID_PASSWORD}' using chap-sha1")
     index = i1.call(".proc_get_index")
     cluster.raft_wait_index(index)
     with pytest.raises(
@@ -755,7 +755,9 @@ def test_submit_sql_after_revoke_login(cluster: Cluster):
 
     password = "Validpa55word"
 
-    acl = i1.sql(f"create user \"alice\" with password '{password}'", sudo=True)
+    acl = i1.sql(
+        f"create user \"alice\" with password '{password}' using chap-sha1", sudo=True
+    )
     assert acl["row_count"] == 1
 
     acl = i1.sql('grant create table to "alice"', sudo=True)
@@ -807,6 +809,7 @@ def test_admin_set_password(cluster: Cluster):
     i1.wait_online()
 
     password = os.getenv("PICODATA_ADMIN_PASSWORD")
+    i1.sql(f"ALTER USER admin WITH PASSWORD '{password}' USING chap-sha1")
     with i1.connect(timeout=5, user="admin", password=password) as conn:
         query = conn.sql(
             'select * from "_pico_user"',
diff --git a/test/int/test_audit.py b/test/int/test_audit.py
index 1f5f20c033..38fb75f1be 100644
--- a/test/int/test_audit.py
+++ b/test/int/test_audit.py
@@ -210,7 +210,7 @@ def test_user(instance_with_audit_file: Instance):
     # https://git.picodata.io/picodata/picodata/picodata/-/issues/449
     instance.sql(
         """
-        alter user "ymir" password 'Topsecre1'
+        alter user "ymir" password 'Topsecre1' using chap-sha1
         """,
         sudo=True,
     )
@@ -519,7 +519,9 @@ def test_access_denied(instance_with_audit_file: Instance):
     instance = instance_with_audit_file
     instance.start()
 
-    instance.create_user(with_name="ymir", with_password="T0psecret")
+    instance.create_user(
+        with_name="ymir", with_password="T0psecret", with_auth="chap-sha1"
+    )
 
     audit = AuditFile(instance.audit_flag_value)
     for _ in audit.events():
@@ -553,7 +555,7 @@ def test_grant_revoke(instance_with_audit_file: Instance):
     user = "ymir"
     password = "T0psecret"
 
-    instance.create_user(with_name=user, with_password=password)
+    instance.create_user(with_name=user, with_password=password, with_auth="chap-sha1")
 
     instance.sql(f'GRANT CREATE ROLE TO "{user}"', sudo=True)
 
diff --git a/test/int/test_basics.py b/test/int/test_basics.py
index 6872adcefa..d67d20740a 100644
--- a/test/int/test_basics.py
+++ b/test/int/test_basics.py
@@ -397,10 +397,10 @@ Insert(_pico_property, ["max_pg_portals",1024]),
 Insert(_pico_property, ["snapshot_chunk_max_size",16777216]),
 Insert(_pico_property, ["snapshot_read_view_close_timeout",86400.0]))|
 |  0  | 1  |BatchDml(
-Insert(_pico_user, [0,"guest",0,["chap-sha1","vhvewKp0tNyweZQ+cFKAlsyphfg="],1,"user"]),
+Insert(_pico_user, [0,"guest",0,["md5","md5084e0343a0486ff05530df6c705c8bb4"],1,"user"]),
 Insert(_pico_privilege, [1,0,"login","universe",0,0]),
 Insert(_pico_privilege, [1,0,"execute","role",2,0]),
-Insert(_pico_user, [1,"admin",0,["chap-sha1",""],1,"user"]),
+Insert(_pico_user, [1,"admin",0,["md5",""],1,"user"]),
 Insert(_pico_privilege, [1,1,"read","universe",0,0]),
 Insert(_pico_privilege, [1,1,"write","universe",0,0]),
 Insert(_pico_privilege, [1,1,"execute","universe",0,0]),
@@ -420,6 +420,7 @@ Insert(_pico_privilege, [1,32,"execute","role",3,0]),
 Insert(_pico_user, [2,"public",0,null,1,"role"]),
 Insert(_pico_user, [31,"super",0,null,1,"role"]),
 Insert(_pico_user, [3,"replication",0,null,1,"role"]))|
+|  0  | 1  |ChangeAuth(1, 0, 1)|
 |  0  | 1  |BatchDml(
 Insert(_pico_table, [{_pico_table},"_pico_table",{{"Global":null}},[{{"field_type":"unsigned","is_nullable":false,"name":"id"}},{{"field_type":"string","is_nullable":false,"name":"name"}},{{"field_type":"map","is_nullable":false,"name":"distribution"}},{{"field_type":"array","is_nullable":false,"name":"format"}},{{"field_type":"unsigned","is_nullable":false,"name":"schema_version"}},{{"field_type":"boolean","is_nullable":false,"name":"operable"}},{{"field_type":"string","is_nullable":false,"name":"engine"}},{{"field_type":"unsigned","is_nullable":false,"name":"owner"}},{{"field_type":"string","is_nullable":false,"name":"description"}}],0,true,"memtx",1,"Stores metadata of all the cluster tables in picodata."]),
 Insert(_pico_index, [{_pico_table},0,"_pico_table_id","tree",[{{"unique":true}}],[["id","unsigned",null,false,null]],true,0]),
diff --git a/test/int/test_cli_connect.py b/test/int/test_cli_connect.py
index c012e45d2c..1ba64f1f65 100644
--- a/test/int/test_cli_connect.py
+++ b/test/int/test_cli_connect.py
@@ -39,7 +39,12 @@ def test_connect_testuser(i1: Instance):
 def test_connect_user_host_port(i1: Instance):
     cli = pexpect.spawn(
         command=i1.binary_path,
-        args=["connect", f"testuser@{i1.host}:{i1.port}", "-u", "overridden"],
+        args=[
+            "connect",
+            f"testuser@{i1.host}:{i1.port}",
+            "-u",
+            "overridden",
+        ],
         encoding="utf-8",
         timeout=1,
     )
@@ -149,7 +154,7 @@ def test_connection_refused(binary_path: str):
 def test_connect_auth_type_ok(i1: Instance):
     cli = pexpect.spawn(
         command=i1.binary_path,
-        args=["connect", f"{i1.host}:{i1.port}", "-u", "testuser", "-a", "chap-sha1"],
+        args=["connect", f"{i1.host}:{i1.port}", "-u", "testuser"],
         encoding="utf-8",
         timeout=1,
     )
@@ -384,6 +389,41 @@ def test_admin_empty_path(binary_path: str):
     cli.expect_exact(pexpect.EOF)
 
 
+def test_admin_with_password(cluster: Cluster):
+    import os
+
+    os.environ["PICODATA_ADMIN_PASSWORD"] = "#AdminX12345"
+
+    i1 = cluster.add_instance(wait_online=False)
+    i1.env.update(os.environ)
+    i1.start()
+    i1.wait_online()
+
+    cli = pexpect.spawn(
+        command=i1.binary_path,
+        args=[
+            "connect",
+            f"{i1.host}:{i1.port}",
+            "-u",
+            "admin",
+        ],
+        env={"NO_COLOR": "1"},
+        encoding="utf-8",
+        timeout=1,
+    )
+    cli.logfile = sys.stdout
+    cli.expect_exact("Enter password for admin: ")
+
+    password = os.getenv("PICODATA_ADMIN_PASSWORD")
+    cli.sendline(password)
+
+    cli.expect_exact("picodata> ")
+
+    eprint("^D")
+    cli.sendcontrol("d")
+    cli.expect_exact(pexpect.EOF)
+
+
 def test_connect_unix_ok_via_default_sock(cluster: Cluster):
     i1 = cluster.add_instance(wait_online=False)
     i1.start()
@@ -499,7 +539,7 @@ def test_connect_with_password_from_file(i1: Instance, binary_path: str):
 def test_connect_connection_info_and_help(i1: Instance):
     cli = pexpect.spawn(
         command=i1.binary_path,
-        args=["connect", f"{i1.host}:{i1.port}", "-u", "testuser", "-a", "chap-sha1"],
+        args=["connect", f"{i1.host}:{i1.port}", "-u", "testuser"],
         encoding="utf-8",
         timeout=1,
     )
diff --git a/test/int/test_ddl.py b/test/int/test_ddl.py
index a0c55b6515..b36d4b3f45 100644
--- a/test/int/test_ddl.py
+++ b/test/int/test_ddl.py
@@ -22,17 +22,17 @@ def test_ddl_abort(cluster: Cluster):
 def test_ddl_create_table_bulky(cluster: Cluster):
     i1, i2, i3, i4 = cluster.deploy(instance_count=4, init_replication_factor=2)
 
-    # At cluster boot schema version is 0
-    assert i1.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-    assert i2.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-    assert i3.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-    assert i4.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-
-    # And next schema version will be 1
-    assert i1.next_schema_version() == 1
-    assert i2.next_schema_version() == 1
-    assert i3.next_schema_version() == 1
-    assert i4.next_schema_version() == 1
+    # At cluster boot schema version is 1
+    assert i1.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+    assert i2.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+    assert i3.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+    assert i4.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+
+    # And next schema version will be 2
+    assert i1.next_schema_version() == 2
+    assert i2.next_schema_version() == 2
+    assert i3.next_schema_version() == 2
+    assert i4.next_schema_version() == 2
 
     ############################################################################
     # Propose a space creation which will fail
@@ -66,16 +66,16 @@ def test_ddl_create_table_bulky(cluster: Cluster):
     assert i4.call("box.space._space:get", space_id) is None
 
     # Schema version hasn't changed
-    assert i1.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-    assert i2.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-    assert i3.call("box.space._pico_property:get", "global_schema_version")[1] == 0
-    assert i4.call("box.space._pico_property:get", "global_schema_version")[1] == 0
+    assert i1.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+    assert i2.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+    assert i3.call("box.space._pico_property:get", "global_schema_version")[1] == 1
+    assert i4.call("box.space._pico_property:get", "global_schema_version")[1] == 1
 
     # But next schema version did change
-    assert i1.next_schema_version() == 2
-    assert i2.next_schema_version() == 2
-    assert i3.next_schema_version() == 2
-    assert i4.next_schema_version() == 2
+    assert i1.next_schema_version() == 3
+    assert i2.next_schema_version() == 3
+    assert i3.next_schema_version() == 3
+    assert i4.next_schema_version() == 3
 
     ############################################################################
     # Propose a space creation which will succeed
@@ -92,16 +92,16 @@ def test_ddl_create_table_bulky(cluster: Cluster):
     space_id = i1.eval("return box.space.stuff.id")
 
     # This time schema version did change
-    assert i1.call("box.space._pico_property:get", "global_schema_version")[1] == 2
-    assert i2.call("box.space._pico_property:get", "global_schema_version")[1] == 2
-    assert i3.call("box.space._pico_property:get", "global_schema_version")[1] == 2
-    assert i4.call("box.space._pico_property:get", "global_schema_version")[1] == 2
+    assert i1.call("box.space._pico_property:get", "global_schema_version")[1] == 3
+    assert i2.call("box.space._pico_property:get", "global_schema_version")[1] == 3
+    assert i3.call("box.space._pico_property:get", "global_schema_version")[1] == 3
+    assert i4.call("box.space._pico_property:get", "global_schema_version")[1] == 3
 
     # And so did next schema version obviously
-    assert i1.next_schema_version() == 3
-    assert i2.next_schema_version() == 3
-    assert i3.next_schema_version() == 3
-    assert i4.next_schema_version() == 3
+    assert i1.next_schema_version() == 4
+    assert i2.next_schema_version() == 4
+    assert i3.next_schema_version() == 4
+    assert i4.next_schema_version() == 4
 
     # Space was created and is operable
     initiator_id = PICO_SERVICE_ID
@@ -110,7 +110,7 @@ def test_ddl_create_table_bulky(cluster: Cluster):
         "stuff",
         {"Global": None},
         [{"field_type": "unsigned", "is_nullable": False, "name": "id"}],
-        2,
+        3,
         True,
         "memtx",
         initiator_id,
@@ -146,7 +146,7 @@ def test_ddl_create_table_bulky(cluster: Cluster):
         [dict(unique=True)],
         [["id", "unsigned", None, False, None]],
         True,
-        2,
+        3,
     ]
     assert i1.call("box.space._pico_index:get", [space_id, 0]) == pico_pk_def
     assert i2.call("box.space._pico_index:get", [space_id, 0]) == pico_pk_def
@@ -171,8 +171,8 @@ def test_ddl_create_table_bulky(cluster: Cluster):
 
     i5 = cluster.add_instance(wait_online=True, replicaset_id="r3")
 
-    assert i5.call("box.space._pico_property:get", "global_schema_version")[1] == 2
-    assert i5.next_schema_version() == 3
+    assert i5.call("box.space._pico_property:get", "global_schema_version")[1] == 3
+    assert i5.next_schema_version() == 4
     assert i5.call("box.space._pico_table:get", space_id) == pico_space_def
     assert i5.call("box.space._pico_index:get", [space_id, 0]) == pico_pk_def
     assert i5.call("box.space._space:get", space_id) == tt_space_def
@@ -181,8 +181,8 @@ def test_ddl_create_table_bulky(cluster: Cluster):
     i6 = cluster.add_instance(wait_online=True, replicaset_id="r3")
 
     # It's schema was updated automatically as well
-    assert i6.call("box.space._pico_property:get", "global_schema_version")[1] == 2
-    assert i6.next_schema_version() == 3
+    assert i6.call("box.space._pico_property:get", "global_schema_version")[1] == 3
+    assert i6.next_schema_version() == 4
     assert i6.call("box.space._pico_table:get", space_id) == pico_space_def
     assert i6.call("box.space._pico_index:get", [space_id, 0]) == pico_pk_def
     assert i6.call("box.space._space:get", space_id) == tt_space_def
@@ -619,14 +619,14 @@ def test_ddl_create_table_from_snapshot_at_boot(cluster: Cluster):
     assert i3.call("box.space._space:get", space_id) == tt_space_def
     assert i3.call("box.space._index:get", [space_id, 0]) == tt_pk_def
     assert i3.call("box.space._index:get", [space_id, 1]) == tt_bucket_id_def
-    assert i3.call("box.space._schema:get", "local_schema_version")[1] == 1
+    assert i3.call("box.space._schema:get", "local_schema_version")[1] == 2
 
     # A replicaset follower boots up from snapshot
     i4 = cluster.add_instance(wait_online=True, replicaset_id="R2")
     assert i4.call("box.space._space:get", space_id) == tt_space_def
     assert i4.call("box.space._index:get", [space_id, 0]) == tt_pk_def
     assert i4.call("box.space._index:get", [space_id, 1]) == tt_bucket_id_def
-    assert i4.call("box.space._schema:get", "local_schema_version")[1] == 1
+    assert i4.call("box.space._schema:get", "local_schema_version")[1] == 2
 
 
 ################################################################################
@@ -690,7 +690,7 @@ def test_ddl_create_table_from_snapshot_at_catchup(cluster: Cluster):
     # A replica catches up by snapshot
     assert i3.call("box.space._space:get", space_id) == tt_space_def
     assert i3.call("box.space._index:get", [space_id, 0]) == tt_pk_def
-    assert i3.call("box.space._schema:get", "local_schema_version")[1] == 1
+    assert i3.call("box.space._schema:get", "local_schema_version")[1] == 2
 
 
 ################################################################################
@@ -1329,7 +1329,7 @@ cluster:
     i2.start()
     i2.wait_online()
 
-    i2.create_user(with_name="andy", with_password="Testpa55")
+    i2.create_user(with_name="andy", with_password="Testpa55", with_auth="chap-sha1")
     i2.sql('GRANT CREATE TABLE TO "andy"', sudo=True)
 
     read_only = i2.eval("return box.cfg.read_only")
diff --git a/test/int/test_gostech_audit.py b/test/int/test_gostech_audit.py
index 083d4bfee4..27313dee62 100644
--- a/test/int/test_gostech_audit.py
+++ b/test/int/test_gostech_audit.py
@@ -319,7 +319,9 @@ def test_gostech_access_denied(
 ) -> None:
     instance, audit = instance_with_gostech_audit
 
-    instance.create_user(with_name="ymir", with_password="T0psecret")
+    instance.create_user(
+        with_name="ymir", with_password="T0psecret", with_auth="chap-sha1"
+    )
 
     expected_error = "Create access to role 'R' is denied for user 'ymir'"
 
@@ -343,7 +345,7 @@ def test_gostech_grant_revoke(
     user = "ymir"
     password = "T0psecret"
 
-    instance.create_user(with_name=user, with_password=password)
+    instance.create_user(with_name=user, with_password=password, with_auth="chap-sha1")
 
     instance.sql(f'GRANT CREATE ROLE TO "{user}"', sudo=True)
     instance.sql(f'GRANT CREATE TABLE TO "{user}"', sudo=True)
diff --git a/test/int/test_sql.py b/test/int/test_sql.py
index fb9403cc28..41e29a8a8f 100644
--- a/test/int/test_sql.py
+++ b/test/int/test_sql.py
@@ -610,7 +610,7 @@ vtable_max_rows = 5000"""
     # test user with write permession can do global dml
     user = "user"
     password = "PaSSW0RD"
-    acl = i1.sql(f"create user {user} with password '{password}'")
+    acl = i1.sql(f"create user {user} with password '{password}' using chap-sha1")
     assert acl["row_count"] == 1
     # check we can't write yet
     with pytest.raises(
@@ -2402,7 +2402,8 @@ def test_sql_alter_login(cluster: Cluster):
     owner_password = "PA5sWORD"
 
     acl = i1.sql(
-        f"create user {owner_username} with password '{owner_password}'", sudo=True
+        f"create user {owner_username} with password '{owner_password}' using chap-sha1",
+        sudo=True,
     )
     assert acl["row_count"] == 1
 
@@ -2413,7 +2414,7 @@ def test_sql_alter_login(cluster: Cluster):
     password = "PA5sWORD"
     # Create user.
     acl = i1.sql(
-        f"create user {username} with password '{password}'",
+        f"create user {username} with password '{password}' using chap-sha1",
         user=owner_username,
         password=owner_password,
     )
@@ -2456,7 +2457,8 @@ def test_sql_alter_login(cluster: Cluster):
     other_username = "other_user"
     other_password = "PA5sWORD"
     acl = i1.sql(
-        f"create user {other_username} with password '{other_password}'", sudo=True
+        f"create user {other_username} with password '{other_password}' using chap-sha1",
+        sudo=True,
     )
     assert acl["row_count"] == 1
     with pytest.raises(
@@ -2497,9 +2499,11 @@ def test_sql_acl_privileges(cluster: Cluster):
     another_rolename = "another_role"
 
     # Create users.
-    acl = i1.sql(f"create user {username} with password '{password}'")
+    acl = i1.sql(f"create user {username} with password '{password}' using chap-sha1")
     assert acl["row_count"] == 1
-    acl = i1.sql(f"create user {another_username} with password '{password}'")
+    acl = i1.sql(
+        f"create user {another_username} with password '{password}' using chap-sha1 "
+    )
     assert acl["row_count"] == 1
     # Create roles.
     acl = i1.sql(f"create role {rolename}")
@@ -3044,11 +3048,12 @@ def test_user_changes_password(cluster: Cluster):
     old_password = "Passw0rd"
     new_password = "Pa55word"
 
-    i1.create_user(with_name=user_name, with_password=old_password)
-
+    i1.create_user(
+        with_name=user_name, with_password=old_password, with_auth="chap-sha1"
+    )
     i1.sql(
         f"""
-        ALTER USER "{user_name}" PASSWORD '{new_password}'
+        ALTER USER "{user_name}" PASSWORD '{new_password}' USING chap-sha1
         """,
         user=user_name,
         password=old_password,
@@ -3879,8 +3884,8 @@ def test_rename_user(cluster: Cluster):
     boba = "boba"
     password = "Passw0rd"
 
-    i1.create_user(with_name=biba, with_password=password)
-    i1.create_user(with_name=boba, with_password=password)
+    i1.create_user(with_name=biba, with_password=password, with_auth="chap-sha1")
+    i1.create_user(with_name=boba, with_password=password, with_auth="chap-sha1")
 
     with pytest.raises(TarantoolError, match=f"user {boba} does not exist"):
         data = i1.sql(
diff --git a/test/pgproto/auth_test.py b/test/pgproto/auth_test.py
index 96a7613804..9b95adbb13 100644
--- a/test/pgproto/auth_test.py
+++ b/test/pgproto/auth_test.py
@@ -1,6 +1,6 @@
 import pytest
 import pg8000.dbapi as pg  # type: ignore
-from conftest import Postgres
+from conftest import Postgres, Cluster
 
 
 def test_auth(postgres: Postgres):
@@ -41,3 +41,38 @@ def test_auth(postgres: Postgres):
         pg.DatabaseError, match=f"authentication failed for user '{sha_user}'"
     ):
         pg.Connection(sha_user, password="aaa", host=postgres.host, port=postgres.port)
+
+
+def test_admin_auth(cluster: Cluster):
+    import os
+
+    os.environ["PICODATA_ADMIN_PASSWORD"] = "#AdminX12345"
+
+    cluster.set_config_file(
+        yaml="""
+    cluster:
+        cluster_id: test
+        tier:
+            default:
+    instance:
+        pg:
+            listen: "127.0.0.1:5432"
+            ssl: False
+    """
+    )
+    i1 = cluster.add_instance(wait_online=False)
+    i1.env.update(os.environ)
+    i1.start()
+    i1.wait_online()
+
+    user = "admin"
+    password = os.getenv("PICODATA_ADMIN_PASSWORD")
+
+    # test authentication with a wrong password
+    with pytest.raises(
+        pg.DatabaseError, match=f"authentication failed for user '{user}'"
+    ):
+        pg.Connection(user, password="wrong password", host="127.0.0.1", port=5432)
+
+    conn = pg.Connection(user=user, password=password, host="127.0.0.1", port=5432)
+    conn.close()
diff --git a/test/pgproto/types_test.py b/test/pgproto/types_test.py
index 07b0f3243b..028bf4a34a 100644
--- a/test/pgproto/types_test.py
+++ b/test/pgproto/types_test.py
@@ -308,13 +308,13 @@ def test_arrays(postgres: Postgres):
     cur = conn.execute(
         """ SELECT \"auth\" FROM \"_pico_user\" WHERE \"id\" = 0; """, binary=False
     )
-    assert cur.fetchall() == [(["chap-sha1", "vhvewKp0tNyweZQ+cFKAlsyphfg="],)]
+    assert cur.fetchall() == [(["md5", "md5084e0343a0486ff05530df6c705c8bb4"],)]
 
     # test binary encoding
     cur = conn.execute(
         """ SELECT \"auth\" FROM \"_pico_user\" WHERE \"id\" = 0; """, binary=True
     )
-    assert cur.fetchall() == [(["chap-sha1", "vhvewKp0tNyweZQ+cFKAlsyphfg="],)]
+    assert cur.fetchall() == [(["md5", "md5084e0343a0486ff05530df6c705c8bb4"],)]
 
     # text array parameters should throw an error
     with pytest.raises(
@@ -343,14 +343,14 @@ def test_arrays(postgres: Postgres):
         """ SELECT \"auth\" FROM \"_pico_user\" WHERE \"name\" = 'admin'; """,
         binary=False,
     )
-    assert cur.fetchall() == [(["chap-sha1", ""],)]
+    assert cur.fetchall() == [(["md5", ""],)]
 
     # bin repr case
     cur = conn.execute(
         """ SELECT \"auth\" FROM \"_pico_user\" WHERE \"name\" = 'admin'; """,
         binary=True,
     )
-    assert cur.fetchall() == [(["chap-sha1", ""],)]
+    assert cur.fetchall() == [(["md5", ""],)]
 
 
 def test_map(postgres: Postgres):
-- 
GitLab