From 379f4764bde7696586d7f93a925e412c6f334a6e Mon Sep 17 00:00:00 2001
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date: Fri, 13 Jan 2023 00:29:27 +0100
Subject: [PATCH] schema: ban replicaset UUID update

It wasn't allowed to drop it, but was allowed to update. The patch
bans it. Firstly, it was not supposed to work. Secondly, a future
patch will introduce a new tuple in _schema, which would store
replicaset UUID too. It won't allow UUID update.

Would be strange, if the update would be let through one _schema
tuple and wouldn't work via another.

Needed for #5029

NO_DOC=bugfix
---
 .../unreleased/replicaset-uuid-update-ban.md  |  3 +++
 src/box/alter.cc                              |  5 ++++
 test/box-luatest/schema_sys_space_test.lua    | 26 +++++++++++++++++++
 3 files changed, 34 insertions(+)
 create mode 100644 changelogs/unreleased/replicaset-uuid-update-ban.md
 create mode 100644 test/box-luatest/schema_sys_space_test.lua

diff --git a/changelogs/unreleased/replicaset-uuid-update-ban.md b/changelogs/unreleased/replicaset-uuid-update-ban.md
new file mode 100644
index 0000000000..b6e5c69ec1
--- /dev/null
+++ b/changelogs/unreleased/replicaset-uuid-update-ban.md
@@ -0,0 +1,3 @@
+## bugfix/replication
+
+* Fixed a bug that allowed to change replicaset UUID via `_schema` space.
diff --git a/src/box/alter.cc b/src/box/alter.cc
index c81f35462a..5255abf10a 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -3978,6 +3978,11 @@ on_replace_dd_schema(struct trigger * /* trigger */, void *event)
 		tt_uuid uu;
 		if (tuple_field_uuid(new_tuple, BOX_SCHEMA_FIELD_VALUE, &uu) != 0)
 			return -1;
+		if (!tt_uuid_is_nil(&REPLICASET_UUID) &&
+		    !tt_uuid_is_equal(&REPLICASET_UUID, &uu)) {
+			diag_set(ClientError, ER_REPLICASET_UUID_IS_RO);
+			return -1;
+		}
 		REPLICASET_UUID = uu;
 		box_broadcast_id();
 		say_info("cluster uuid %s", tt_uuid_str(&uu));
diff --git a/test/box-luatest/schema_sys_space_test.lua b/test/box-luatest/schema_sys_space_test.lua
new file mode 100644
index 0000000000..f8fde9eded
--- /dev/null
+++ b/test/box-luatest/schema_sys_space_test.lua
@@ -0,0 +1,26 @@
+local server = require('luatest.server')
+local t = require('luatest')
+local g = t.group()
+
+g.before_all = function(lg)
+    lg.server = server:new({alias = 'master'})
+    lg.server:start()
+end
+
+g.after_all = function(lg)
+    lg.server:drop()
+end
+
+g.test_cluster_uuid_update_ban = function(lg)
+    lg.server:exec(function()
+        local uuid = require('uuid')
+        local _schema = box.space._schema
+        local msg = "Can't reset replica set UUID"
+        t.assert_error_msg_contains(msg, _schema.replace, _schema,
+                                    {'cluster', uuid.str()})
+        t.assert_error_msg_contains(msg, _schema.replace, _schema,
+                                    {'cluster', tostring(uuid.NULL)})
+        -- Fine to replace with the same value.
+        _schema:replace{'cluster', box.info.cluster.uuid}
+    end)
+end
-- 
GitLab