|
|
|
@ -14,14 +14,23 @@ |
|
|
|
|
|
|
|
|
|
#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/statusor.h" |
|
|
|
|
#include "absl/strings/string_view.h" |
|
|
|
|
#include "gmock/gmock.h" |
|
|
|
|
#include "gtest/gtest.h" |
|
|
|
|
|
|
|
|
|
#include <grpc/grpc.h> |
|
|
|
|
#include <grpc/grpc_audit_logging.h> |
|
|
|
|
#include <grpc/slice.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_impl.h" |
|
|
|
|
#include "test/core/util/test_config.h" |
|
|
|
@ -30,8 +39,68 @@ namespace grpc_core { |
|
|
|
|
namespace testing { |
|
|
|
|
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.
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, EmptyRbacPolicy) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, EmptyRbacPolicy) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -53,7 +122,7 @@ TEST(RbacServiceConfigParsingTest, EmptyRbacPolicy) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test basic parsing of RBAC policy
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, RbacPolicyWithoutRules) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, RbacPolicyWithoutRules) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -80,7 +149,7 @@ TEST(RbacServiceConfigParsingTest, RbacPolicyWithoutRules) { |
|
|
|
|
|
|
|
|
|
// Test that RBAC policies are not parsed if the channel arg
|
|
|
|
|
// GRPC_ARG_PARSE_RBAC_METHOD_CONFIG is not present
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, MissingChannelArg) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, MissingChannelArg) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -102,7 +171,7 @@ TEST(RbacServiceConfigParsingTest, MissingChannelArg) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test an empty rbacPolicy array
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, EmptyRbacPolicyArray) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, EmptyRbacPolicyArray) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -124,7 +193,7 @@ TEST(RbacServiceConfigParsingTest, EmptyRbacPolicyArray) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test presence of multiple RBAC policies in the array
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, MultipleRbacPolicies) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, MultipleRbacPolicies) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -155,7 +224,7 @@ TEST(RbacServiceConfigParsingTest, MultipleRbacPolicies) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, BadRbacPolicyType) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, BadRbacPolicyType) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -174,7 +243,7 @@ TEST(RbacServiceConfigParsingTest, BadRbacPolicyType) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, BadRulesType) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, BadRulesType) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -193,7 +262,7 @@ TEST(RbacServiceConfigParsingTest, BadRulesType) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, BadActionAndPolicyType) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, BadActionAndPolicyType) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -221,7 +290,7 @@ TEST(RbacServiceConfigParsingTest, BadActionAndPolicyType) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, MissingPermissionAndPrincipals) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, MissingPermissionAndPrincipals) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -252,7 +321,7 @@ TEST(RbacServiceConfigParsingTest, MissingPermissionAndPrincipals) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, EmptyPrincipalAndPermission) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, EmptyPrincipalAndPermission) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -285,7 +354,7 @@ TEST(RbacServiceConfigParsingTest, EmptyPrincipalAndPermission) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsTypes) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsTypes) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -343,7 +412,7 @@ TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsTypes) { |
|
|
|
|
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -438,7 +507,7 @@ TEST(RbacServiceConfigParsingTest, VariousPermissionsAndPrincipalsBadTypes) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, HeaderMatcherVariousTypes) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, HeaderMatcherVariousTypes) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -483,7 +552,7 @@ TEST(RbacServiceConfigParsingTest, HeaderMatcherVariousTypes) { |
|
|
|
|
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, HeaderMatcherBadTypes) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, HeaderMatcherBadTypes) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -540,7 +609,7 @@ TEST(RbacServiceConfigParsingTest, HeaderMatcherBadTypes) { |
|
|
|
|
<< service_config.status(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, StringMatcherVariousTypes) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, StringMatcherVariousTypes) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -582,7 +651,7 @@ TEST(RbacServiceConfigParsingTest, StringMatcherVariousTypes) { |
|
|
|
|
EXPECT_EQ(parsed_rbac_config->authorization_engine(0)->num_policies(), 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(RbacServiceConfigParsingTest, StringMatcherBadTypes) { |
|
|
|
|
TEST_F(RbacServiceConfigParsingTest, StringMatcherBadTypes) { |
|
|
|
|
const char* test_json = |
|
|
|
|
"{\n" |
|
|
|
|
" \"methodConfig\": [ {\n" |
|
|
|
@ -638,6 +707,205 @@ TEST(RbacServiceConfigParsingTest, StringMatcherBadTypes) { |
|
|
|
|
<< 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 testing
|
|
|
|
|
} // namespace grpc_core
|
|
|
|
|