You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pegasus.apache.org by la...@apache.org on 2023/02/28 02:58:22 UTC
[incubator-pegasus] branch master updated: feat(security): Use Apache Ranger for access control(1/n) (#1360)
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 cd01040d8 feat(security): Use Apache Ranger for access control(1/n) (#1360)
cd01040d8 is described below
commit cd01040d86b250d1183b943147ef0a551ec8e248
Author: WHBANG <38...@users.noreply.github.com>
AuthorDate: Tue Feb 28 10:58:16 2023 +0800
feat(security): Use Apache Ranger for access control(1/n) (#1360)
---
src/runtime/CMakeLists.txt | 2 +
src/runtime/ranger/CMakeLists.txt | 30 +++++++++
src/runtime/ranger/ranger_resource_policy.cpp | 82 +++++++++++++++++++++++
src/runtime/ranger/ranger_resource_policy.h | 85 ++++++++++++++++++++++++
src/runtime/test/ranger_resource_policy_test.cpp | 80 ++++++++++++++++++++++
5 files changed, 279 insertions(+)
diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt
index 736cfa22d..d5757717a 100644
--- a/src/runtime/CMakeLists.txt
+++ b/src/runtime/CMakeLists.txt
@@ -26,9 +26,11 @@ add_subdirectory(test)
add_subdirectory(rpc)
add_subdirectory(task)
add_subdirectory(security)
+add_subdirectory(ranger)
# TODO(zlw) remove perf_counter from dsn_runtime after the refactor by WuTao
add_library(dsn_runtime STATIC
+ $<TARGET_OBJECTS:dsn_ranger>
$<TARGET_OBJECTS:dsn.security>
$<TARGET_OBJECTS:dsn.rpc>
$<TARGET_OBJECTS:dsn.task>
diff --git a/src/runtime/ranger/CMakeLists.txt b/src/runtime/ranger/CMakeLists.txt
new file mode 100644
index 000000000..3c3e441a4
--- /dev/null
+++ b/src/runtime/ranger/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+set(MY_PROJ_NAME dsn_ranger)
+
+# Search mode for source files under CURRENT project directory?
+# "GLOB_RECURSE" for recursive search
+# "GLOB" for non-recursive search
+set(MY_SRC_SEARCH_MODE "GLOB")
+
+set(MY_PROJ_LIBS "")
+
+# Extra files that will be installed
+set(MY_BINPLACES "")
+
+dsn_add_object()
diff --git a/src/runtime/ranger/ranger_resource_policy.cpp b/src/runtime/ranger/ranger_resource_policy.cpp
new file mode 100644
index 000000000..220c07bab
--- /dev/null
+++ b/src/runtime/ranger/ranger_resource_policy.cpp
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "ranger_resource_policy.h"
+
+namespace dsn {
+namespace ranger {
+
+/*extern*/ access_type operator|(access_type lhs, access_type rhs)
+{
+ using act = std::underlying_type<access_type>::type;
+ return access_type(static_cast<act>(lhs) | static_cast<act>(rhs));
+}
+
+/*extern*/ access_type operator&(access_type lhs, access_type rhs)
+{
+ using act = std::underlying_type<access_type>::type;
+ return access_type(static_cast<act>(lhs) & static_cast<act>(rhs));
+}
+
+bool policy_item::match(const access_type &ac_type, const std::string &user_name) const
+{
+ return static_cast<bool>(access_types & ac_type) && users.count(user_name) != 0;
+}
+
+bool acl_policies::allowed(const access_type &ac_type, const std::string &user_name) const
+{
+ // 1. Check if it is not allowed.
+ for (const auto &deny_policy : deny_policies) {
+ // 1.1. In 'deny_policies'.
+ if (!deny_policy.match(ac_type, user_name)) {
+ continue;
+ }
+ bool in_deny_policies_exclude = false;
+ for (const auto &deny_policy_exclude : deny_policies_exclude) {
+ if (deny_policy_exclude.match(ac_type, user_name)) {
+ in_deny_policies_exclude = true;
+ break;
+ }
+ }
+ // 1.2. Not in any 'deny_policies_exclude', it's not allowed.
+ if (!in_deny_policies_exclude) {
+ return false;
+ }
+ }
+
+ // 2. Check if it is allowed.
+ for (const auto &allow_policy : allow_policies) {
+ // 2.1. In 'allow_policies'.
+ if (!allow_policy.match(ac_type, user_name)) {
+ continue;
+ }
+ for (const auto &allow_policy_exclude : allow_policies_exclude) {
+ // 2.2. In some 'allow_policies_exclude', it's not allowed.
+ if (allow_policy_exclude.match(ac_type, user_name)) {
+ return false;
+ }
+ }
+ // 2.3. Not in any 'allow_policies_exclude', it's allowed.
+ return true;
+ }
+
+ // 3. Otherwise, it's not allowed.
+ return false;
+}
+
+} // namespace ranger
+} // namespace dsn
diff --git a/src/runtime/ranger/ranger_resource_policy.h b/src/runtime/ranger/ranger_resource_policy.h
new file mode 100644
index 000000000..1708e5f72
--- /dev/null
+++ b/src/runtime/ranger/ranger_resource_policy.h
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include <rapidjson/document.h>
+
+#include "common/json_helper.h"
+#include "utils/fmt_logging.h"
+
+namespace dsn {
+namespace ranger {
+
+// ACL type defined in Range service for RPC matching policy
+enum class access_type : uint8_t
+{
+ KRead = 1,
+ KWrite = 1 << 1,
+ KCreate = 1 << 2,
+ KDrop = 1 << 3,
+ KList = 1 << 4,
+ KMetadata = 1 << 5,
+ KControl = 1 << 6
+};
+
+extern access_type operator|(access_type lhs, access_type rhs);
+
+extern access_type operator&(access_type lhs, access_type rhs);
+
+// Ranger policy data structure
+struct policy_item
+{
+ access_type access_types;
+ std::unordered_set<std::string> users;
+
+ // Check if the 'acl_type' - 'user_name' pair is matched to the policy.
+ // Return true if it is matched, otherwise return false.
+ // TODO(wanghao): add benchmark test
+ bool match(const access_type &ac_type, const std::string &user_name) const;
+};
+
+// Data structure of policies with different priorities
+struct acl_policies
+{
+ // policy priority: deny_policies_exclude > deny_policies > allow_policies_exclude >
+ // allow_policies
+ std::vector<policy_item> allow_policies;
+ std::vector<policy_item> allow_policies_exclude;
+ std::vector<policy_item> deny_policies;
+ std::vector<policy_item> deny_policies_exclude;
+
+ // Check whether the 'user_name' is allowed to access the resource by type of 'ac_type'.
+ bool allowed(const access_type &ac_type, const std::string &user_name) const;
+};
+
+// A policy data structure definition of ranger resources
+struct ranger_resource_policy
+{
+ std::string name;
+ std::unordered_set<std::string> database_names;
+ std::unordered_set<std::string> table_names;
+ acl_policies policies;
+};
+
+} // namespace ranger
+} // namespace dsn
diff --git a/src/runtime/test/ranger_resource_policy_test.cpp b/src/runtime/test/ranger_resource_policy_test.cpp
new file mode 100644
index 000000000..7e7efcc73
--- /dev/null
+++ b/src/runtime/test/ranger_resource_policy_test.cpp
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <gtest/gtest.h>
+
+#include "runtime/ranger/ranger_resource_policy.h"
+
+namespace dsn {
+namespace ranger {
+
+TEST(ranger_resource_policy_test, policy_item_match)
+{
+ policy_item item = {access_type::KRead | access_type::KWrite | access_type::KCreate,
+ {"user1", "user2"}};
+ struct test_case
+ {
+ access_type ac_type;
+ std::string user_name;
+ bool expected_result;
+ } tests[] = {{access_type::KRead, "", false},
+ {access_type::KRead, "user", false},
+ {access_type::KRead, "user1", true},
+ {access_type::KWrite, "user1", true},
+ {access_type::KCreate, "user1", true},
+ {access_type::KDrop, "user1", false},
+ {access_type::KList, "user1", false},
+ {access_type::KMetadata, "user1", false},
+ {access_type::KControl, "user1", false},
+ {access_type::KWrite, "user2", true}};
+ for (const auto &test : tests) {
+ auto actual_result = item.match(test.ac_type, test.user_name);
+ EXPECT_EQ(test.expected_result, actual_result);
+ }
+}
+
+TEST(ranger_resource_policy_test, acl_policies_allowed)
+{
+ acl_policies policy;
+ policy.allow_policies = {{access_type::KRead | access_type::KWrite | access_type::KCreate,
+ {"user1", "user2", "user3", "user4"}}};
+ policy.allow_policies_exclude = {{access_type::KWrite | access_type::KCreate, {"user2"}}};
+ policy.deny_policies = {{access_type::KRead | access_type::KWrite, {"user3", "user4"}}};
+ policy.deny_policies_exclude = {{access_type::KRead, {"user4"}}};
+ struct test_case
+ {
+ access_type ac_type;
+ std::string user_name;
+ bool expected_result;
+ } tests[] = {{access_type::KRead, "user", false}, {access_type::KRead, "user1", true},
+ {access_type::KWrite, "user1", true}, {access_type::KCreate, "user1", true},
+ {access_type::KDrop, "user1", false}, {access_type::KList, "user1", false},
+ {access_type::KMetadata, "user1", false}, {access_type::KControl, "user1", false},
+ {access_type::KRead, "user2", true}, {access_type::KWrite, "user2", false},
+ {access_type::KCreate, "user2", false}, {access_type::KDrop, "user2", false},
+ {access_type::KList, "user2", false}, {access_type::KMetadata, "user2", false},
+ {access_type::KControl, "user2", false}, {access_type::KRead, "user3", false},
+ {access_type::KCreate, "user3", true}, {access_type::KList, "user3", false},
+ {access_type::KRead, "user4", true}, {access_type::KWrite, "user4", false},
+ {access_type::KCreate, "user4", true}, {access_type::KList, "user4", false}};
+ for (const auto &test : tests) {
+ auto actual_result = policy.allowed(test.ac_type, test.user_name);
+ EXPECT_EQ(test.expected_result, actual_result);
+ }
+}
+} // namespace ranger
+} // namespace dsn
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pegasus.apache.org
For additional commands, e-mail: commits-help@pegasus.apache.org