Revert "[Audit Logging] Audit logging config translation by rbac service config parser" (#33178)

Reverts grpc/grpc#33145

It causes internal breakages.
pull/33183/head
Eugene Ostroukhov 2 years ago committed by GitHub
parent 57cd079310
commit 922b18f71b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      include/grpc/grpc_audit_logging.h
  2. 1
      src/core/BUILD
  3. 98
      src/core/ext/filters/rbac/rbac_service_config_parser.cc
  4. 8
      src/core/lib/security/authorization/grpc_authorization_engine.h
  5. 1
      src/core/lib/security/authorization/stdout_logger.h
  6. 300
      test/core/ext/filters/rbac/rbac_service_config_parser_test.cc
  7. 1
      test/core/security/grpc_audit_logging_test.cc
  8. 1
      test/core/security/grpc_authorization_engine_test.cc

@ -62,7 +62,6 @@ class AuditContext {
class AuditLogger { class AuditLogger {
public: public:
virtual ~AuditLogger() = default; virtual ~AuditLogger() = default;
virtual absl::string_view name() const = 0;
virtual void Log(const AuditContext& audit_context) = 0; virtual void Log(const AuditContext& audit_context) = 0;
}; };

@ -3697,7 +3697,6 @@ grpc_cc_library(
"channel_fwd", "channel_fwd",
"closure", "closure",
"error", "error",
"grpc_audit_logging",
"grpc_authorization_base", "grpc_authorization_base",
"grpc_matchers", "grpc_matchers",
"grpc_rbac_engine", "grpc_rbac_engine",

@ -20,29 +20,21 @@
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <memory>
#include <string> #include <string>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include <grpc/grpc_audit_logging.h>
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/json/json_args.h" #include "src/core/lib/json/json_args.h"
#include "src/core/lib/json/json_object_loader.h" #include "src/core/lib/json/json_object_loader.h"
#include "src/core/lib/matchers/matchers.h" #include "src/core/lib/matchers/matchers.h"
#include "src/core/lib/security/authorization/audit_logging.h"
namespace grpc_core { namespace grpc_core {
namespace { namespace {
using experimental::AuditLoggerFactory;
using experimental::AuditLoggerRegistry;
// RbacConfig: one or more RbacPolicy structs // RbacConfig: one or more RbacPolicy structs
struct RbacConfig { struct RbacConfig {
// RbacPolicy: optional Rules // RbacPolicy: optional Rules
@ -187,21 +179,8 @@ struct RbacConfig {
static const JsonLoaderInterface* JsonLoader(const JsonArgs&); static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
}; };
// AuditLogger: the name of logger and its config in json
struct AuditLogger {
std::string name;
Json::Object config;
static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
void JsonPostLoad(const Json&, const JsonArgs&,
ValidationErrors* errors);
};
int action; int action;
std::map<std::string, Policy> policies; std::map<std::string, Policy> policies;
// Defaults to kNone since its json field is optional.
Rbac::AuditCondition audit_condition = Rbac::AuditCondition::kNone;
std::vector<std::unique_ptr<AuditLoggerFactory::Config>> logger_configs;
Rules() = default; Rules() = default;
Rules(const Rules&) = delete; Rules(const Rules&) = delete;
@ -209,7 +188,7 @@ struct RbacConfig {
Rules(Rules&&) = default; Rules(Rules&&) = default;
Rules& operator=(Rules&&) = default; Rules& operator=(Rules&&) = default;
Rbac TakeAsRbac(std::string name); Rbac TakeAsRbac();
static const JsonLoaderInterface* JsonLoader(const JsonArgs&); static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors); void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors);
}; };
@ -737,51 +716,24 @@ const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::JsonLoader(
return loader; return loader;
} }
//
// RbacConfig::RbacPolicy::Rules::AuditLogger
//
const JsonLoaderInterface*
RbacConfig::RbacPolicy::Rules::AuditLogger::JsonLoader(const JsonArgs&) {
// All fields handled in JsonPostLoad().
static const auto* loader = JsonObjectLoader<AuditLogger>().Finish();
return loader;
}
void RbacConfig::RbacPolicy::Rules::AuditLogger::JsonPostLoad(
const Json& json, const JsonArgs& args, ValidationErrors* errors) {
// Should have exactly one field as the logger name.
if (json.object().size() != 1) {
errors->AddError("audit logger should have exactly one field");
return;
}
name = json.object().begin()->first;
auto config_or =
LoadJsonObjectField<Json::Object>(json.object(), args, name, errors);
if (config_or.has_value()) {
config = std::move(*config_or);
}
}
// //
// RbacConfig::RbacPolicy::Rules // RbacConfig::RbacPolicy::Rules
// //
Rbac RbacConfig::RbacPolicy::Rules::TakeAsRbac(std::string name) { Rbac RbacConfig::RbacPolicy::Rules::TakeAsRbac() {
Rbac rbac; Rbac rbac;
rbac.name = std::move(name); // TODO(lwge): This is to fix msan failure for now. Add proper conversion once
// audit logging support is added.
rbac.audit_condition = Rbac::AuditCondition::kNone;
rbac.action = static_cast<Rbac::Action>(action); rbac.action = static_cast<Rbac::Action>(action);
rbac.audit_condition = audit_condition;
for (auto& p : policies) { for (auto& p : policies) {
rbac.policies.emplace(p.first, p.second.TakeAsRbacPolicy()); rbac.policies.emplace(p.first, p.second.TakeAsRbacPolicy());
} }
rbac.logger_configs = std::move(logger_configs);
return rbac; return rbac;
} }
const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::JsonLoader( const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::JsonLoader(
const JsonArgs&) { const JsonArgs&) {
// Audit logger configs handled in post load.
static const auto* loader = JsonObjectLoader<Rules>() static const auto* loader = JsonObjectLoader<Rules>()
.Field("action", &Rules::action) .Field("action", &Rules::action)
.OptionalField("policies", &Rules::policies) .OptionalField("policies", &Rules::policies)
@ -789,8 +741,7 @@ const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::JsonLoader(
return loader; return loader;
} }
void RbacConfig::RbacPolicy::Rules::JsonPostLoad(const Json& json, void RbacConfig::RbacPolicy::Rules::JsonPostLoad(const Json&, const JsonArgs&,
const JsonArgs& args,
ValidationErrors* errors) { ValidationErrors* errors) {
// Validate action field. // Validate action field.
auto rbac_action = static_cast<Rbac::Action>(action); auto rbac_action = static_cast<Rbac::Action>(action);
@ -799,40 +750,6 @@ void RbacConfig::RbacPolicy::Rules::JsonPostLoad(const Json& json,
ValidationErrors::ScopedField field(errors, ".action"); ValidationErrors::ScopedField field(errors, ".action");
errors->AddError("unknown action"); errors->AddError("unknown action");
} }
// Parse and validate audit_condition field.
auto condition = LoadJsonObjectField<int>(json.object(), args,
"audit_condition", errors, false);
if (condition.has_value()) {
switch (*condition) {
case static_cast<int>(Rbac::AuditCondition::kNone):
case static_cast<int>(Rbac::AuditCondition::kOnAllow):
case static_cast<int>(Rbac::AuditCondition::kOnDeny):
case static_cast<int>(Rbac::AuditCondition::kOnDenyAndAllow):
audit_condition = static_cast<Rbac::AuditCondition>(*condition);
break;
default: {
ValidationErrors::ScopedField field(errors, ".audit_condition");
errors->AddError("unknown audit condition");
}
}
}
// Parse and validate audit logger configs.
auto configs = LoadJsonObjectField<std::vector<AuditLogger>>(
json.object(), args, "audit_loggers", errors, false);
if (configs.has_value()) {
for (size_t i = 0; i < configs->size(); ++i) {
auto& logger = (*configs)[i];
auto config = AuditLoggerRegistry::ParseConfig(
logger.name, Json::FromObject(std::move(logger.config)));
if (!config.ok()) {
ValidationErrors::ScopedField field(
errors, absl::StrCat(".audit_loggers[", i, "]"));
errors->AddError(config.status().message());
continue;
}
logger_configs.push_back(std::move(*config));
}
}
} }
// //
@ -845,7 +762,8 @@ Rbac RbacConfig::RbacPolicy::TakeAsRbac() {
// is equivalent to no enforcing. // is equivalent to no enforcing.
return Rbac(std::move(name), Rbac::Action::kDeny, {}); return Rbac(std::move(name), Rbac::Action::kDeny, {});
} }
return rules->TakeAsRbac(std::move(name)); // TODO(lwge): This also needs to take the name.
return rules->TakeAsRbac();
} }
const JsonLoaderInterface* RbacConfig::RbacPolicy::JsonLoader(const JsonArgs&) { const JsonLoaderInterface* RbacConfig::RbacPolicy::JsonLoader(const JsonArgs&) {

@ -56,14 +56,6 @@ class GrpcAuthorizationEngine : public AuthorizationEngine {
// Required only for testing purpose. // Required only for testing purpose.
size_t num_policies() const { return policies_.size(); } size_t num_policies() const { return policies_.size(); }
// Required only for testing purpose.
Rbac::AuditCondition audit_condition() const { return audit_condition_; }
// Required only for testing purpose.
const std::vector<std::unique_ptr<AuditLogger>>& audit_loggers() const {
return audit_loggers_;
}
// Evaluates incoming request against RBAC policy and makes a decision to // Evaluates incoming request against RBAC policy and makes a decision to
// whether allow/deny this request. // whether allow/deny this request.
Decision Evaluate(const EvaluateArgs& args) const override; Decision Evaluate(const EvaluateArgs& args) const override;

@ -32,7 +32,6 @@ namespace experimental {
class StdoutAuditLogger : public AuditLogger { class StdoutAuditLogger : public AuditLogger {
public: public:
StdoutAuditLogger() = default; StdoutAuditLogger() = default;
absl::string_view name() const override { return "stdout_logger"; }
void Log(const AuditContext&) override; void Log(const AuditContext&) override;
}; };

@ -14,23 +14,14 @@
#include "src/core/ext/filters/rbac/rbac_service_config_parser.h" #include "src/core/ext/filters/rbac/rbac_service_config_parser.h"
#include <map>
#include <memory>
#include <string>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/grpc_audit_logging.h>
#include <grpc/slice.h> #include <grpc/slice.h>
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/json/json_writer.h"
#include "src/core/lib/security/authorization/audit_logging.h"
#include "src/core/lib/service_config/service_config.h" #include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_impl.h" #include "src/core/lib/service_config/service_config_impl.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
@ -39,68 +30,8 @@ namespace grpc_core {
namespace testing { namespace testing {
namespace { namespace {
using experimental::AuditContext;
using experimental::AuditLogger;
using experimental::AuditLoggerFactory;
using experimental::AuditLoggerRegistry;
using experimental::RegisterAuditLoggerFactory;
constexpr absl::string_view kLoggerName = "test_logger";
class TestAuditLogger : public AuditLogger {
public:
TestAuditLogger() = default;
absl::string_view name() const override { return kLoggerName; }
void Log(const AuditContext&) override {}
};
class TestAuditLoggerFactory : public AuditLoggerFactory {
public:
class Config : public AuditLoggerFactory::Config {
public:
explicit Config(const Json& json) : config_(JsonDump(json)) {}
absl::string_view name() const override { return kLoggerName; }
std::string ToString() const override { return config_; }
private:
std::string config_;
};
explicit TestAuditLoggerFactory(
std::map<absl::string_view, std::string>* configs)
: configs_(configs) {}
absl::string_view name() const override { return kLoggerName; }
absl::StatusOr<std::unique_ptr<AuditLoggerFactory::Config>>
ParseAuditLoggerConfig(const Json& json) override {
// Invalidate configs with "bad" field in it.
if (json.object().find("bad") != json.object().end()) {
return absl::InvalidArgumentError("bad logger config");
}
return std::make_unique<Config>(json);
}
std::unique_ptr<AuditLogger> CreateAuditLogger(
std::unique_ptr<AuditLoggerFactory::Config> config) override {
// Only insert entry to the map when logger is created.
configs_->emplace(name(), config->ToString());
return std::make_unique<TestAuditLogger>();
}
private:
std::map<absl::string_view, std::string>* configs_;
};
class RbacServiceConfigParsingTest : public ::testing::Test {
protected:
void SetUp() override {
RegisterAuditLoggerFactory(
std::make_unique<TestAuditLoggerFactory>(&logger_configs_));
}
void TearDown() override { AuditLoggerRegistry::TestOnlyResetRegistry(); }
std::map<absl::string_view, std::string> logger_configs_;
};
// Filter name is required in RBAC policy. // Filter name is required in RBAC policy.
TEST_F(RbacServiceConfigParsingTest, EmptyRbacPolicy) { TEST(RbacServiceConfigParsingTest, EmptyRbacPolicy) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -122,7 +53,7 @@ TEST_F(RbacServiceConfigParsingTest, EmptyRbacPolicy) {
} }
// Test basic parsing of RBAC policy // Test basic parsing of RBAC policy
TEST_F(RbacServiceConfigParsingTest, RbacPolicyWithoutRules) { TEST(RbacServiceConfigParsingTest, RbacPolicyWithoutRules) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -149,7 +80,7 @@ TEST_F(RbacServiceConfigParsingTest, RbacPolicyWithoutRules) {
// Test that RBAC policies are not parsed if the channel arg // Test that RBAC policies are not parsed if the channel arg
// GRPC_ARG_PARSE_RBAC_METHOD_CONFIG is not present // GRPC_ARG_PARSE_RBAC_METHOD_CONFIG is not present
TEST_F(RbacServiceConfigParsingTest, MissingChannelArg) { TEST(RbacServiceConfigParsingTest, MissingChannelArg) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -171,7 +102,7 @@ TEST_F(RbacServiceConfigParsingTest, MissingChannelArg) {
} }
// Test an empty rbacPolicy array // Test an empty rbacPolicy array
TEST_F(RbacServiceConfigParsingTest, EmptyRbacPolicyArray) { TEST(RbacServiceConfigParsingTest, EmptyRbacPolicyArray) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -193,7 +124,7 @@ TEST_F(RbacServiceConfigParsingTest, EmptyRbacPolicyArray) {
} }
// Test presence of multiple RBAC policies in the array // Test presence of multiple RBAC policies in the array
TEST_F(RbacServiceConfigParsingTest, MultipleRbacPolicies) { TEST(RbacServiceConfigParsingTest, MultipleRbacPolicies) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -224,7 +155,7 @@ TEST_F(RbacServiceConfigParsingTest, MultipleRbacPolicies) {
} }
} }
TEST_F(RbacServiceConfigParsingTest, BadRbacPolicyType) { TEST(RbacServiceConfigParsingTest, BadRbacPolicyType) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -243,7 +174,7 @@ TEST_F(RbacServiceConfigParsingTest, BadRbacPolicyType) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, BadRulesType) { TEST(RbacServiceConfigParsingTest, BadRulesType) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -262,7 +193,7 @@ TEST_F(RbacServiceConfigParsingTest, BadRulesType) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, BadActionAndPolicyType) { TEST(RbacServiceConfigParsingTest, BadActionAndPolicyType) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -290,7 +221,7 @@ TEST_F(RbacServiceConfigParsingTest, BadActionAndPolicyType) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, MissingPermissionAndPrincipals) { TEST(RbacServiceConfigParsingTest, MissingPermissionAndPrincipals) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -321,7 +252,7 @@ TEST_F(RbacServiceConfigParsingTest, MissingPermissionAndPrincipals) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, EmptyPrincipalAndPermission) { TEST(RbacServiceConfigParsingTest, EmptyPrincipalAndPermission) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -354,7 +285,7 @@ TEST_F(RbacServiceConfigParsingTest, EmptyPrincipalAndPermission) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsTypes) { TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsTypes) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -412,7 +343,7 @@ TEST_F(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsTypes) {
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1); EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1);
} }
TEST_F(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) { TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -507,7 +438,7 @@ TEST_F(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, HeaderMatcherVariousTypes) { TEST(RbacServiceConfigParsingTest, HeaderMatcherVariousTypes) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -552,7 +483,7 @@ TEST_F(RbacServiceConfigParsingTest, HeaderMatcherVariousTypes) {
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1); EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1);
} }
TEST_F(RbacServiceConfigParsingTest, HeaderMatcherBadTypes) { TEST(RbacServiceConfigParsingTest, HeaderMatcherBadTypes) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -609,7 +540,7 @@ TEST_F(RbacServiceConfigParsingTest, HeaderMatcherBadTypes) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, StringMatcherVariousTypes) { TEST(RbacServiceConfigParsingTest, StringMatcherVariousTypes) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -651,7 +582,7 @@ TEST_F(RbacServiceConfigParsingTest, StringMatcherVariousTypes) {
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1); EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1);
} }
TEST_F(RbacServiceConfigParsingTest, StringMatcherBadTypes) { TEST(RbacServiceConfigParsingTest, StringMatcherBadTypes) {
const char* test_json = const char* test_json =
"{\n" "{\n"
" \"methodConfig\": [ {\n" " \"methodConfig\": [ {\n"
@ -707,205 +638,6 @@ TEST_F(RbacServiceConfigParsingTest, StringMatcherBadTypes) {
<< service_config.status(); << service_config.status();
} }
TEST_F(RbacServiceConfigParsingTest, AuditConditionOnDenyWithMultipleLoggers) {
const char* test_json =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" {}\n"
" ],\n"
" \"rbacPolicy\": [ {\n"
" \"filter_name\": \"rbac\",\n"
" \"rules\":{\n"
" \"action\":1,\n"
" \"audit_condition\":1,\n"
" \"audit_loggers\":[ \n"
" {\n"
" \"stdout_logger\": {}\n"
" },\n"
" {\n"
" \"test_logger\": {\"foo\": \"bar\"}\n"
" }\n"
" ]\n"
" }\n"
" } ]\n"
" } ]\n"
"}";
ChannelArgs args = ChannelArgs().Set(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, 1);
auto service_config = ServiceConfigImpl::Create(args, test_json);
ASSERT_TRUE(service_config.status().ok());
const auto* vector_ptr =
(*service_config)->GetMethodParsedConfigVector(grpc_empty_slice());
ASSERT_NE(vector_ptr, nullptr);
auto* parsed_rbac_config = static_cast<RbacMethodParsedConfig*>(
((*vector_ptr)[RbacServiceConfigParser::ParserIndex()]).get());
ASSERT_NE(parsed_rbac_config, nullptr);
ASSERT_NE(parsed_rbac_config->authorization_engine(0), nullptr);
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->audit_condition(),
Rbac::AuditCondition::kOnDeny);
EXPECT_THAT(parsed_rbac_config->authorization_engine(0)->audit_loggers(),
::testing::ElementsAre(::testing::Pointee(::testing::Property(
&AuditLogger::name, "stdout_logger")),
::testing::Pointee(::testing::Property(
&AuditLogger::name, kLoggerName))));
EXPECT_THAT(logger_configs_, ::testing::ElementsAre(::testing::Pair(
"test_logger", "{\"foo\":\"bar\"}")));
}
TEST_F(RbacServiceConfigParsingTest, BadAuditLoggerConfig) {
const char* test_json =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" {}\n"
" ],\n"
" \"rbacPolicy\": [ {\n"
" \"filter_name\": \"rbac\",\n"
" \"rules\":{\n"
" \"action\":1,\n"
" \"audit_condition\":1,\n"
" \"audit_loggers\":[ \n"
" {\n"
" \"test_logger\": {\"bad\": \"bar\"}\n"
" }\n"
" ]\n"
" }\n"
" } ]\n"
" } ]\n"
"}";
ChannelArgs args = ChannelArgs().Set(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, 1);
auto service_config = ServiceConfigImpl::Create(args, test_json);
EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(service_config.status().message(),
"errors validating service config: ["
"field:methodConfig[0].rbacPolicy[0].rules.audit_loggers[0] "
"error:bad logger config]")
<< service_config.status();
}
TEST_F(RbacServiceConfigParsingTest, UnknownAuditLoggerConfig) {
const char* test_json =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" {}\n"
" ],\n"
" \"rbacPolicy\": [ {\n"
" \"filter_name\": \"rbac\",\n"
" \"rules\":{\n"
" \"action\":1,\n"
" \"audit_condition\":1,\n"
" \"audit_loggers\":[ \n"
" {\n"
" \"unknown_logger\": {}\n"
" }\n"
" ]\n"
" }\n"
" } ]\n"
" } ]\n"
"}";
ChannelArgs args = ChannelArgs().Set(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, 1);
auto service_config = ServiceConfigImpl::Create(args, test_json);
EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(service_config.status().message(),
"errors validating service config: ["
"field:methodConfig[0].rbacPolicy[0].rules.audit_loggers[0] "
"error:audit logger factory for unknown_logger does not exist]")
<< service_config.status();
}
TEST_F(RbacServiceConfigParsingTest, BadAuditConditionAndLoggersTypes) {
const char* test_json =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" {}\n"
" ],\n"
" \"rbacPolicy\": [ {\n"
" \"filter_name\": \"rbac\",\n"
" \"rules\":{\n"
" \"action\":1,\n"
" \"audit_condition\":{},\n"
" \"audit_loggers\":{}\n"
" }\n"
" } ]\n"
" } ]\n"
"}";
ChannelArgs args = ChannelArgs().Set(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, 1);
auto service_config = ServiceConfigImpl::Create(args, test_json);
EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(service_config.status().message(),
"errors validating service config: ["
"field:methodConfig[0].rbacPolicy[0].rules.audit_condition "
"error:is not a number; "
"field:methodConfig[0].rbacPolicy[0].rules.audit_loggers "
"error:is not an array]")
<< service_config.status();
}
TEST_F(RbacServiceConfigParsingTest, BadAuditConditionEnum) {
const char* test_json =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" {}\n"
" ],\n"
" \"rbacPolicy\": [ {\n"
" \"filter_name\": \"rbac\",\n"
" \"rules\":{\n"
" \"action\":1,\n"
" \"audit_condition\":100\n"
" }\n"
" } ]\n"
" } ]\n"
"}";
ChannelArgs args = ChannelArgs().Set(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, 1);
auto service_config = ServiceConfigImpl::Create(args, test_json);
EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(service_config.status().message(),
"errors validating service config: ["
"field:methodConfig[0].rbacPolicy[0].rules.audit_condition "
"error:unknown audit condition]")
<< service_config.status();
}
TEST_F(RbacServiceConfigParsingTest, BadAuditLoggerObject) {
const char* test_json =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" {}\n"
" ],\n"
" \"rbacPolicy\": [ {\n"
" \"filter_name\": \"rbac\",\n"
" \"rules\":{\n"
" \"action\":1,\n"
" \"audit_condition\":1,\n"
" \"audit_loggers\":[ \n"
" {\n"
" \"stdout_logger\": {},\n"
" \"foo\": {}\n"
" },\n"
" {\n"
" \"stdout_logger\": 123\n"
" }\n"
" ]\n"
" }\n"
" } ]\n"
" } ]\n"
"}";
ChannelArgs args = ChannelArgs().Set(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, 1);
auto service_config = ServiceConfigImpl::Create(args, test_json);
EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(service_config.status().message(),
"errors validating service config: "
"[field:methodConfig[0].rbacPolicy[0].rules.audit_loggers[0] "
"error:audit logger should have exactly one field; "
"field:methodConfig[0].rbacPolicy[0].rules.audit_loggers[1].stdout_"
"logger error:is not an object]")
<< service_config.status();
}
} // namespace } // namespace
} // namespace testing } // namespace testing
} // namespace grpc_core } // namespace grpc_core

@ -54,7 +54,6 @@ namespace {
class TestAuditLogger : public AuditLogger { class TestAuditLogger : public AuditLogger {
public: public:
absl::string_view name() const override { return "test_logger"; }
void Log(const AuditContext&) override {} void Log(const AuditContext&) override {}
}; };

@ -65,7 +65,6 @@ class TestAuditLogger : public AuditLogger {
std::vector<std::unique_ptr<TestAuditContext>>* contexts) std::vector<std::unique_ptr<TestAuditContext>>* contexts)
: contexts_(contexts) {} : contexts_(contexts) {}
absl::string_view name() const override { return kLoggerName; }
void Log(const AuditContext& context) override { void Log(const AuditContext& context) override {
contexts_->push_back(std::make_unique<TestAuditContext>(context)); contexts_->push_back(std::make_unique<TestAuditContext>(context));
} }

Loading…
Cancel
Save