src/runtime/ranger/ranger_resource_policy.cpp (202 lines of code) (raw):
// 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"
#include "runtime/ranger/access_type.h"
#include "utils/fmt_logging.h"
namespace dsn {
namespace ranger {
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;
}
template <>
policy_check_status
acl_policies::policies_check<policy_check_type::kAllow>(const access_type &ac_type,
const std::string &user_name) const
{
return do_policies_check<policy_check_type::kAllow, policy_check_status::kAllowed>(ac_type,
user_name);
}
template <>
policy_check_status
acl_policies::policies_check<policy_check_type::kDeny>(const access_type &ac_type,
const std::string &user_name) const
{
return do_policies_check<policy_check_type::kDeny, policy_check_status::kDenied>(ac_type,
user_name);
}
template <>
policy_check_status
acl_policies::do_policies_check<policy_check_type::kAllow, policy_check_status::kAllowed>(
const access_type &ac_type, const std::string &user_name) const
{
for (const auto &policy : allow_policies) {
// 1. Doesn't match an allow_policies.
if (!policy.match(ac_type, user_name)) {
continue;
}
// 2. Matches a policy.
for (const auto &exclude_policy : allow_policies_exclude) {
if (exclude_policy.match(ac_type, user_name)) {
// 2.1. Matches an allow_policies_exclude.
return policy_check_status::kPending;
}
}
// 2.2. Doesn't match any allow_exclude_policies.
return policy_check_status::kAllowed;
}
// 3. Doesn't match any policy.
return policy_check_status::kNotMatched;
}
template <>
policy_check_status
acl_policies::do_policies_check<policy_check_type::kDeny, policy_check_status::kDenied>(
const access_type &ac_type, const std::string &user_name) const
{
for (const auto &policy : deny_policies) {
// 1. Doesn't match a deny_policies.
if (!policy.match(ac_type, user_name)) {
continue;
}
// 2. Matches a policy.
for (const auto &exclude_policy : deny_policies_exclude) {
if (exclude_policy.match(ac_type, user_name)) {
// 2.1. Matches a deny_policies_exclude.
return policy_check_status::kPending;
}
}
// 2.2. Doesn't match any deny_exclude_policies.
return policy_check_status::kDenied;
}
// 3. Doesn't match any policy.
return policy_check_status::kNotMatched;
}
access_control_result
check_ranger_resource_policy_allowed(const std::vector<ranger_resource_policy> &policies,
const access_type &ac_type,
const std::string &user_name,
const match_database_type &md_type,
const std::string &database_name,
const std::string &default_database_name)
{
// Check if it is denied by any policy in current resource.
auto check_res = do_check_ranger_resource_policy<policy_check_type::kDeny>(
policies, ac_type, user_name, md_type, database_name, default_database_name);
if (access_control_result::kDenied == check_res) {
return access_control_result::kDenied;
}
CHECK(access_control_result::kPending == check_res, "the access control result must kPending.");
// Check if it is allowed by any policy in current resource.
check_res = do_check_ranger_resource_policy<policy_check_type::kAllow>(
policies, ac_type, user_name, md_type, database_name, default_database_name);
if (access_control_result::kAllowed == check_res) {
return access_control_result::kAllowed;
}
CHECK(access_control_result::kPending == check_res, "the access control result must kPending.");
// The check that does not match any policy in current reosource returns false.
return access_control_result::kDenied;
}
template <>
access_control_result do_check_ranger_resource_policy<policy_check_type::kAllow>(
const std::vector<ranger_resource_policy> &policies,
const access_type &ac_type,
const std::string &user_name,
const match_database_type &md_type,
const std::string &database_name,
const std::string &default_database_name)
{
for (const auto &policy : policies) {
if (match_database_type::kNeed == md_type) {
// Lagacy table not match any database.
if (database_name.empty() && policy.database_names.count("*") == 0 &&
policy.database_names.count(default_database_name) == 0) {
continue;
}
// New table not match any database.
if (!database_name.empty() && policy.database_names.count("*") == 0 &&
policy.database_names.count(database_name) == 0) {
continue;
}
}
auto check_status =
policy.policies.policies_check<policy_check_type::kAllow>(ac_type, user_name);
if (policy_check_status::kAllowed == check_status) {
return access_control_result::kAllowed;
}
// In a 'allow_policies' and in a 'allow_policies_exclude' or not match.
CHECK(policy_check_status::kPending == check_status ||
policy_check_status::kNotMatched == check_status,
"the policy check status must be kPending or kNotMatched");
}
return access_control_result::kPending;
}
template <>
access_control_result do_check_ranger_resource_policy<policy_check_type::kDeny>(
const std::vector<ranger_resource_policy> &policies,
const access_type &ac_type,
const std::string &user_name,
const match_database_type &md_type,
const std::string &database_name,
const std::string &default_database_name)
{
for (const auto &policy : policies) {
if (match_database_type::kNeed == md_type) {
// Lagacy table not match any database.
if (database_name.empty() && policy.database_names.count("*") == 0 &&
policy.database_names.count(default_database_name) == 0) {
continue;
}
// New table not match any database.
if (!database_name.empty() && policy.database_names.count("*") == 0 &&
policy.database_names.count(database_name) == 0) {
continue;
}
}
auto check_status =
policy.policies.policies_check<policy_check_type::kDeny>(ac_type, user_name);
if (policy_check_status::kDenied == check_status) {
return access_control_result::kDenied;
}
// In a 'deny_policies' and in a 'deny_policies_exclude' or not match.
CHECK(policy_check_status::kPending == check_status ||
policy_check_status::kNotMatched == check_status,
"the policy check status must be kPending or kNotMatched");
}
return access_control_result::kPending;
}
access_control_result check_ranger_database_table_policy_allowed(
const std::vector<matched_database_table_policy> &policies,
const access_type &ac_type,
const std::string &user_name)
{
// Check if it is denied by any DATABASE_TABLE policy.
auto check_res = do_check_ranger_database_table_policy<policy_check_type::kDeny>(
policies, ac_type, user_name);
if (access_control_result::kDenied == check_res) {
return access_control_result::kDenied;
}
CHECK(access_control_result::kPending == check_res, "the access control result must kPending.");
// Check if it is allowed by any DATABASE_TABLE policy.
check_res = do_check_ranger_database_table_policy<policy_check_type::kAllow>(
policies, ac_type, user_name);
if (access_control_result::kAllowed == check_res) {
return access_control_result::kAllowed;
}
CHECK(access_control_result::kPending == check_res, "the access control result must kPending.");
// The check that does not match any DATABASE_TABLE policy returns false.
return access_control_result::kDenied;
}
template <>
access_control_result do_check_ranger_database_table_policy<policy_check_type::kDeny>(
const std::vector<matched_database_table_policy> &policies,
const access_type &ac_type,
const std::string &user_name)
{
for (const auto &policy : policies) {
auto check_status =
policy.policies.policies_check<policy_check_type::kDeny>(ac_type, user_name);
// When policy_check_type is 'kDeny' and in a 'deny_policies' and not in any
// 'deny_policies_exclude'.
if (policy_check_status::kDenied == check_status) {
return access_control_result::kDenied;
}
// In a 'policies' and in a 'policies_exclude' or not match.
CHECK(policy_check_status::kPending == check_status ||
policy_check_status::kNotMatched == check_status,
"the policy check status must be kPending or kNotMatched");
}
return access_control_result::kPending;
}
template <>
access_control_result do_check_ranger_database_table_policy<policy_check_type::kAllow>(
const std::vector<matched_database_table_policy> &policies,
const access_type &ac_type,
const std::string &user_name)
{
for (const auto &policy : policies) {
auto check_status =
policy.policies.policies_check<policy_check_type::kAllow>(ac_type, user_name);
// When policy_check_type is 'kAllow' and in a 'allow_policies' and not in any
// 'allow_policies_exclude'.
if (policy_check_status::kAllowed == check_status) {
return access_control_result::kAllowed;
}
// In a 'policies' and in a 'policies_exclude' or not match.
CHECK(policy_check_status::kPending == check_status ||
policy_check_status::kNotMatched == check_status,
"the policy check status must be kPending or kNotMatched");
}
return access_control_result::kPending;
}
} // namespace ranger
} // namespace dsn