This is an automated email from the ASF dual-hosted git repository.
laiyingchun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pegasus.git
The following commit(s) were added to refs/heads/master by this push:
new bcc5f658b fix(backup): validate backup policy name (#2029)
bcc5f658b is described below
commit bcc5f658b5b98d5b8348cf8b5cb0fb4a912a5d78
Author: Yingchun Lai <[email protected]>
AuthorDate: Mon May 27 16:14:01 2024 +0800
fix(backup): validate backup policy name (#2029)
Because the backup policy name will be used as a metric name and label, it
should not contain any invalid character (e.g. `-`), otherwise, it lead
crash.
This patch adds a validator to ensure there are only allowed characters in
backup policy name.
---
src/meta/CMakeLists.txt | 1 +
src/meta/meta_backup_service.cpp | 44 ++++++++++++++++++++++++++++++++------
src/meta/meta_backup_service.h | 3 ++-
src/meta/test/meta_backup_test.cpp | 26 ++++++++++++++++++++++
4 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/src/meta/CMakeLists.txt b/src/meta/CMakeLists.txt
index 95ecb3b9a..eb5ff8d3c 100644
--- a/src/meta/CMakeLists.txt
+++ b/src/meta/CMakeLists.txt
@@ -39,6 +39,7 @@ set(MY_PROJ_LIBS
dsn_http
dsn_runtime
dsn_aio
+ prometheus-cpp-core
zookeeper
hashtable
hdfs
diff --git a/src/meta/meta_backup_service.cpp b/src/meta/meta_backup_service.cpp
index 5f8d04b55..84b9cd79e 100644
--- a/src/meta/meta_backup_service.cpp
+++ b/src/meta/meta_backup_service.cpp
@@ -19,6 +19,7 @@
#include <boost/cstdint.hpp>
#include <boost/lexical_cast.hpp>
#include <fmt/core.h>
+#include <prometheus/check_names.h>
#include <algorithm>
#include <iterator>
#include <type_traits>
@@ -41,9 +42,9 @@
#include "runtime/rpc/rpc_holder.h"
#include "runtime/rpc/rpc_message.h"
#include "runtime/rpc/serialization.h"
-#include "security/access_controller.h"
#include "runtime/task/async_calls.h"
#include "runtime/task/task_code.h"
+#include "security/access_controller.h"
#include "server_state.h"
#include "utils/autoref_ptr.h"
#include "utils/blob.h"
@@ -1349,9 +1350,10 @@ void backup_service::add_backup_policy(dsn::message_ex
*msg)
{
// check policy name
zauto_lock l(_lock);
- if (!is_valid_policy_name_unlocked(request.policy_name)) {
+ if (!is_valid_policy_name_unlocked(request.policy_name, hint_message))
{
response.err = ERR_INVALID_PARAMETERS;
- response.hint_message = "invalid policy_name: " +
request.policy_name;
+ response.hint_message =
+ fmt::format("invalid policy name: '{}', {}",
request.policy_name, hint_message);
_meta_svc->reply_data(msg, response);
msg->release_ref();
return;
@@ -1459,10 +1461,40 @@ void backup_service::do_update_policy_to_remote_storage(
});
}
-bool backup_service::is_valid_policy_name_unlocked(const std::string
&policy_name)
+bool backup_service::is_valid_policy_name_unlocked(const std::string
&policy_name,
+ std::string &hint_message)
{
- auto iter = _policy_states.find(policy_name);
- return (iter == _policy_states.end());
+ // BACKUP_INFO and policy_name should not be the same, because they are in
the same level in the
+ // output when query the policy details, use different names to
distinguish the respective
+ // contents.
+ static const std::set<std::string> kReservedNames =
{cold_backup_constant::BACKUP_INFO};
+ if (kReservedNames.count(policy_name) == 1) {
+ hint_message = "policy name is reserved";
+ return false;
+ }
+
+ // Validate the policy name as a metric name in prometheus.
+ if (!prometheus::CheckMetricName(policy_name)) {
+ hint_message = "policy name should match regex
'[a-zA-Z_:][a-zA-Z0-9_:]*' when act as a "
+ "metric name in prometheus";
+ return false;
+ }
+
+ // Validate the policy name as a metric label in prometheus.
+ if (!prometheus::CheckLabelName(policy_name,
prometheus::MetricType::Gauge)) {
+ hint_message = "policy name should match regex
'[a-zA-Z_][a-zA-Z0-9_]*' when act as a "
+ "metric label in prometheus";
+ return false;
+ }
+
+ const auto iter = _policy_states.find(policy_name);
+ if (iter != _policy_states.end()) {
+ hint_message = "policy name is already exist";
+ return false;
+ }
+
+ hint_message.clear();
+ return true;
}
void backup_service::query_backup_policy(query_backup_policy_rpc rpc)
diff --git a/src/meta/meta_backup_service.h b/src/meta/meta_backup_service.h
index f767ad2be..d3bf9fac8 100644
--- a/src/meta/meta_backup_service.h
+++ b/src/meta/meta_backup_service.h
@@ -407,6 +407,7 @@ private:
FRIEND_TEST(backup_service_test, test_init_backup);
FRIEND_TEST(backup_service_test, test_query_backup_status);
+ FRIEND_TEST(backup_service_test, test_valid_policy_name);
FRIEND_TEST(meta_backup_service_test, test_add_backup_policy);
void start_create_policy_meta_root(dsn::task_ptr callback);
@@ -420,7 +421,7 @@ private:
const policy &p,
std::shared_ptr<policy_context>
&p_context_ptr);
- bool is_valid_policy_name_unlocked(const std::string &policy_name);
+ bool is_valid_policy_name_unlocked(const std::string &policy_name,
std::string &hint_message);
policy_factory _factory;
meta_service *_meta_svc;
diff --git a/src/meta/test/meta_backup_test.cpp
b/src/meta/test/meta_backup_test.cpp
index 5a77b13bc..4d1f21493 100644
--- a/src/meta/test/meta_backup_test.cpp
+++ b/src/meta/test/meta_backup_test.cpp
@@ -19,6 +19,7 @@
#include <map>
#include <memory>
#include <string>
+// IWYU pragma: no_include <type_traits>
#include <utility>
#include <vector>
@@ -204,6 +205,31 @@ TEST_F(backup_service_test, test_query_backup_status)
ASSERT_EQ(1, resp.backup_items.size());
}
+TEST_F(backup_service_test, test_valid_policy_name)
+{
+ std::string hint_message;
+
ASSERT_FALSE(_backup_service->is_valid_policy_name_unlocked(cold_backup_constant::BACKUP_INFO,
+ hint_message));
+ ASSERT_EQ("policy name is reserved", hint_message);
+
+
ASSERT_FALSE(_backup_service->is_valid_policy_name_unlocked("bad-policy-name",
hint_message));
+ ASSERT_EQ("policy name should match regex '[a-zA-Z_:][a-zA-Z0-9_:]*' when
act as a metric name "
+ "in prometheus",
+ hint_message);
+
+
ASSERT_FALSE(_backup_service->is_valid_policy_name_unlocked("bad_policy_name:",
hint_message));
+ ASSERT_EQ("policy name should match regex '[a-zA-Z_][a-zA-Z0-9_]*' when
act as a metric label "
+ "in prometheus",
+ hint_message);
+
+ _backup_service->_policy_states.insert(std::make_pair("exist_policy_name",
nullptr));
+
ASSERT_FALSE(_backup_service->is_valid_policy_name_unlocked("exist_policy_name",
hint_message));
+ ASSERT_EQ("policy name is already exist", hint_message);
+
+
ASSERT_TRUE(_backup_service->is_valid_policy_name_unlocked("new_policy_name0",
hint_message));
+ ASSERT_TRUE(hint_message.empty());
+}
+
class backup_engine_test : public meta_test_base
{
public:
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]