RBAC Engine implementation. (#25948)

pull/26111/head
Ashitha Santhosh 4 years ago committed by GitHub
parent c3a91f8c82
commit 457fd3d41c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      BUILD
  2. 44
      CMakeLists.txt
  3. 30
      build_autogenerated.yaml
  4. 44
      src/core/lib/security/authorization/authorization_engine.h
  5. 4
      src/core/lib/security/authorization/evaluate_args.h
  6. 49
      src/core/lib/security/authorization/grpc_authorization_engine.cc
  7. 55
      src/core/lib/security/authorization/grpc_authorization_engine.h
  8. 13
      test/core/security/BUILD
  9. 107
      test/core/security/grpc_authorization_engine_test.cc
  10. 2
      test/core/util/evaluate_args_test_util.h
  11. 24
      tools/run_tests/generated/tests.json

@ -2065,11 +2065,14 @@ grpc_cc_library(
name = "grpc_rbac_engine",
srcs = [
"src/core/lib/security/authorization/evaluate_args.cc",
"src/core/lib/security/authorization/grpc_authorization_engine.cc",
"src/core/lib/security/authorization/matchers.cc",
"src/core/lib/security/authorization/rbac_policy.cc",
],
hdrs = [
"src/core/lib/security/authorization/authorization_engine.h",
"src/core/lib/security/authorization/evaluate_args.h",
"src/core/lib/security/authorization/grpc_authorization_engine.h",
"src/core/lib/security/authorization/matchers.h",
"src/core/lib/security/authorization/rbac_policy.h",
],

@ -857,6 +857,7 @@ if(gRPC_BUILD_TESTS)
endif()
add_dependencies(buildtests_cxx global_config_test)
add_dependencies(buildtests_cxx google_mesh_ca_certificate_provider_factory_test)
add_dependencies(buildtests_cxx grpc_authorization_engine_test)
add_dependencies(buildtests_cxx grpc_cli)
add_dependencies(buildtests_cxx grpc_tls_certificate_distributor_test)
add_dependencies(buildtests_cxx grpc_tls_certificate_provider_test)
@ -8015,6 +8016,7 @@ if(gRPC_BUILD_TESTS)
add_executable(authorization_matchers_test
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_authorization_engine.cc
src/core/lib/security/authorization/matchers.cc
src/core/lib/security/authorization/rbac_policy.cc
test/core/security/authorization_matchers_test.cc
@ -9129,6 +9131,7 @@ if(gRPC_BUILD_TESTS)
add_executable(cel_authorization_engine_test
src/core/lib/security/authorization/cel_authorization_engine.cc
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_authorization_engine.cc
src/core/lib/security/authorization/matchers.cc
src/core/lib/security/authorization/rbac_policy.cc
test/core/security/cel_authorization_engine_test.cc
@ -10312,6 +10315,7 @@ if(gRPC_BUILD_TESTS)
add_executable(evaluate_args_test
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_authorization_engine.cc
src/core/lib/security/authorization/matchers.cc
src/core/lib/security/authorization/rbac_policy.cc
test/core/security/evaluate_args_test.cc
@ -10722,6 +10726,45 @@ target_link_libraries(google_mesh_ca_certificate_provider_factory_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(grpc_authorization_engine_test
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_authorization_engine.cc
src/core/lib/security/authorization/matchers.cc
src/core/lib/security/authorization/rbac_policy.cc
test/core/security/grpc_authorization_engine_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(grpc_authorization_engine_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(grpc_authorization_engine_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -12755,6 +12798,7 @@ if(gRPC_BUILD_TESTS)
add_executable(rbac_translator_test
src/core/lib/security/authorization/evaluate_args.cc
src/core/lib/security/authorization/grpc_authorization_engine.cc
src/core/lib/security/authorization/matchers.cc
src/core/lib/security/authorization/rbac_policy.cc
src/core/lib/security/authorization/rbac_translator.cc

@ -4229,11 +4229,14 @@ targets:
build: test
language: c++
headers:
- src/core/lib/security/authorization/authorization_engine.h
- src/core/lib/security/authorization/evaluate_args.h
- src/core/lib/security/authorization/grpc_authorization_engine.h
- src/core/lib/security/authorization/matchers.h
- src/core/lib/security/authorization/rbac_policy.h
src:
- src/core/lib/security/authorization/evaluate_args.cc
- src/core/lib/security/authorization/grpc_authorization_engine.cc
- src/core/lib/security/authorization/matchers.cc
- src/core/lib/security/authorization/rbac_policy.cc
- test/core/security/authorization_matchers_test.cc
@ -4648,8 +4651,10 @@ targets:
build: test
language: c++
headers:
- src/core/lib/security/authorization/authorization_engine.h
- src/core/lib/security/authorization/cel_authorization_engine.h
- src/core/lib/security/authorization/evaluate_args.h
- src/core/lib/security/authorization/grpc_authorization_engine.h
- src/core/lib/security/authorization/matchers.h
- src/core/lib/security/authorization/mock_cel/activation.h
- src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h
@ -4661,6 +4666,7 @@ targets:
src:
- src/core/lib/security/authorization/cel_authorization_engine.cc
- src/core/lib/security/authorization/evaluate_args.cc
- src/core/lib/security/authorization/grpc_authorization_engine.cc
- src/core/lib/security/authorization/matchers.cc
- src/core/lib/security/authorization/rbac_policy.cc
- test/core/security/cel_authorization_engine_test.cc
@ -5049,11 +5055,14 @@ targets:
build: test
language: c++
headers:
- src/core/lib/security/authorization/authorization_engine.h
- src/core/lib/security/authorization/evaluate_args.h
- src/core/lib/security/authorization/grpc_authorization_engine.h
- src/core/lib/security/authorization/matchers.h
- src/core/lib/security/authorization/rbac_policy.h
src:
- src/core/lib/security/authorization/evaluate_args.cc
- src/core/lib/security/authorization/grpc_authorization_engine.cc
- src/core/lib/security/authorization/matchers.cc
- src/core/lib/security/authorization/rbac_policy.cc
- test/core/security/evaluate_args_test.cc
@ -5170,6 +5179,24 @@ targets:
- test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc
deps:
- grpc_test_util
- name: grpc_authorization_engine_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/security/authorization/authorization_engine.h
- src/core/lib/security/authorization/evaluate_args.h
- src/core/lib/security/authorization/grpc_authorization_engine.h
- src/core/lib/security/authorization/matchers.h
- src/core/lib/security/authorization/rbac_policy.h
src:
- src/core/lib/security/authorization/evaluate_args.cc
- src/core/lib/security/authorization/grpc_authorization_engine.cc
- src/core/lib/security/authorization/matchers.cc
- src/core/lib/security/authorization/rbac_policy.cc
- test/core/security/grpc_authorization_engine_test.cc
deps:
- grpc_test_util
- name: grpc_cli
build: test
run: false
@ -5931,12 +5958,15 @@ targets:
build: test
language: c++
headers:
- src/core/lib/security/authorization/authorization_engine.h
- src/core/lib/security/authorization/evaluate_args.h
- src/core/lib/security/authorization/grpc_authorization_engine.h
- src/core/lib/security/authorization/matchers.h
- src/core/lib/security/authorization/rbac_policy.h
- src/core/lib/security/authorization/rbac_translator.h
src:
- src/core/lib/security/authorization/evaluate_args.cc
- src/core/lib/security/authorization/grpc_authorization_engine.cc
- src/core/lib/security/authorization/matchers.cc
- src/core/lib/security/authorization/rbac_policy.cc
- src/core/lib/security/authorization/rbac_translator.cc

@ -0,0 +1,44 @@
// Copyright 2021 gRPC authors.
//
// Licensed 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.
#ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_ENGINE_H
#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_ENGINE_H
#include <grpc/support/port_platform.h>
#include <string>
#include "src/core/lib/security/authorization/evaluate_args.h"
namespace grpc_core {
// Interface for gRPC Authorization Engine.
class AuthorizationEngine {
public:
struct Decision {
enum class Type {
kAllow,
kDeny,
};
Type type;
std::string matching_policy_name;
};
virtual ~AuthorizationEngine() = default;
virtual Decision Evaluate(const EvaluateArgs& args) const = 0;
};
} // namespace grpc_core
#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_ENGINE_H

@ -69,8 +69,8 @@ class EvaluateArgs {
absl::string_view GetCommonName() const;
private:
grpc_metadata_batch* metadata_ = nullptr;
PerChannelArgs* channel_args_ = nullptr;
grpc_metadata_batch* metadata_;
PerChannelArgs* channel_args_;
};
} // namespace grpc_core

@ -0,0 +1,49 @@
// Copyright 2021 gRPC authors.
//
// Licensed 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/authorization/grpc_authorization_engine.h"
namespace grpc_core {
GrpcAuthorizationEngine::GrpcAuthorizationEngine(Rbac policy)
: action_(policy.action) {
for (auto& sub_policy : policy.policies) {
Policy policy;
policy.name = sub_policy.first;
policy.matcher = absl::make_unique<PolicyAuthorizationMatcher>(
std::move(sub_policy.second));
policies_.push_back(std::move(policy));
}
}
AuthorizationEngine::Decision GrpcAuthorizationEngine::Evaluate(
const EvaluateArgs& args) const {
Decision decision;
bool matches = false;
for (const auto& policy : policies_) {
if (policy.matcher->Matches(args)) {
matches = true;
decision.matching_policy_name = policy.name;
break;
}
}
decision.type = (matches == (action_ == Rbac::Action::kAllow))
? Decision::Type::kAllow
: Decision::Type::kDeny;
return decision;
}
} // namespace grpc_core

@ -0,0 +1,55 @@
// Copyright 2021 gRPC authors.
//
// Licensed 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.
#ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H
#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/security/authorization/authorization_engine.h"
#include "src/core/lib/security/authorization/matchers.h"
#include "src/core/lib/security/authorization/rbac_policy.h"
namespace grpc_core {
// GrpcAuthorizationEngine can be either an Allow engine or Deny engine. This
// engine makes authorization decisions to Allow or Deny incoming RPC request
// based on permission and principal configs in the provided RBAC policy and the
// engine type. This engine ignores condition field in RBAC config. It is the
// caller's responsibility to provide RBAC policies that are compatible with
// this engine.
class GrpcAuthorizationEngine : public AuthorizationEngine {
public:
// Builds GrpcAuthorizationEngine without any policies.
explicit GrpcAuthorizationEngine(Rbac::Action action) : action_(action) {}
// Builds GrpcAuthorizationEngine with allow/deny RBAC policy.
explicit GrpcAuthorizationEngine(Rbac policy);
// Evaluates incoming request against RBAC policy and makes a decision to
// whether allow/deny this request.
Decision Evaluate(const EvaluateArgs& args) const override;
private:
struct Policy {
std::string name;
std::unique_ptr<AuthorizationMatcher> matcher;
};
Rbac::Action action_;
std::vector<Policy> policies_;
};
} // namespace grpc_core
#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H

@ -438,3 +438,16 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "grpc_authorization_engine_test",
srcs = ["grpc_authorization_engine_test.cc"],
external_deps = ["gtest"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//:grpc_rbac_engine",
"//test/core/util:grpc_test_util",
],
)

@ -0,0 +1,107 @@
// Copyright 2021 gRPC authors.
//
// Licensed 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 <grpc/support/port_platform.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/core/lib/security/authorization/grpc_authorization_engine.h"
namespace grpc_core {
TEST(GrpcAuthorizationEngineTest, AllowEngineWithMatchingPolicy) {
Rbac::Policy policy1(
Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true),
Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true));
Rbac::Policy policy2((Rbac::Permission(Rbac::Permission::RuleType::kAny)),
(Rbac::Principal(Rbac::Principal::RuleType::kAny)));
std::map<std::string, Rbac::Policy> policies;
policies["policy1"] = std::move(policy1);
policies["policy2"] = std::move(policy2);
Rbac rbac(Rbac::Action::kAllow, std::move(policies));
GrpcAuthorizationEngine engine(std::move(rbac));
AuthorizationEngine::Decision decision =
engine.Evaluate(EvaluateArgs(nullptr, nullptr));
EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
EXPECT_EQ(decision.matching_policy_name, "policy2");
}
TEST(GrpcAuthorizationEngineTest, AllowEngineWithNoMatchingPolicy) {
Rbac::Policy policy1(
Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true),
Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true));
std::map<std::string, Rbac::Policy> policies;
policies["policy1"] = std::move(policy1);
Rbac rbac(Rbac::Action::kAllow, std::move(policies));
GrpcAuthorizationEngine engine(std::move(rbac));
AuthorizationEngine::Decision decision =
engine.Evaluate(EvaluateArgs(nullptr, nullptr));
EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
EXPECT_TRUE(decision.matching_policy_name.empty());
}
TEST(GrpcAuthorizationEngineTest, AllowEngineWithEmptyPolicies) {
GrpcAuthorizationEngine engine(Rbac::Action::kAllow);
AuthorizationEngine::Decision decision =
engine.Evaluate(EvaluateArgs(nullptr, nullptr));
EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
EXPECT_TRUE(decision.matching_policy_name.empty());
}
TEST(GrpcAuthorizationEngineTest, DenyEngineWithMatchingPolicy) {
Rbac::Policy policy1(
Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true),
Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true));
Rbac::Policy policy2((Rbac::Permission(Rbac::Permission::RuleType::kAny)),
(Rbac::Principal(Rbac::Principal::RuleType::kAny)));
std::map<std::string, Rbac::Policy> policies;
policies["policy1"] = std::move(policy1);
policies["policy2"] = std::move(policy2);
Rbac rbac(Rbac::Action::kDeny, std::move(policies));
GrpcAuthorizationEngine engine(std::move(rbac));
AuthorizationEngine::Decision decision =
engine.Evaluate(EvaluateArgs(nullptr, nullptr));
EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
EXPECT_EQ(decision.matching_policy_name, "policy2");
}
TEST(GrpcAuthorizationEngineTest, DenyEngineWithNoMatchingPolicy) {
Rbac::Policy policy1(
Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true),
Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true));
std::map<std::string, Rbac::Policy> policies;
policies["policy1"] = std::move(policy1);
Rbac rbac(Rbac::Action::kDeny, std::move(policies));
GrpcAuthorizationEngine engine(std::move(rbac));
AuthorizationEngine::Decision decision =
engine.Evaluate(EvaluateArgs(nullptr, nullptr));
EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
EXPECT_TRUE(decision.matching_policy_name.empty());
}
TEST(GrpcAuthorizationEngineTest, DenyEngineWithEmptyPolicies) {
GrpcAuthorizationEngine engine(Rbac::Action::kDeny);
AuthorizationEngine::Decision decision =
engine.Evaluate(EvaluateArgs(nullptr, nullptr));
EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
EXPECT_TRUE(decision.matching_policy_name.empty());
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -22,8 +22,6 @@
#include <gtest/gtest.h>
#include "src/core/lib/security/authorization/evaluate_args.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "test/core/util/mock_authorization_endpoint.h"
namespace grpc_core {

@ -4627,6 +4627,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "grpc_authorization_engine_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save