Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Audit Logging] Xds Audit Logger Registry. #32828

Merged
merged 29 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3f49062
Create the structure of the xDS audit logger registry.
rockspore Apr 6, 2023
d67fa5f
newlines
rockspore Apr 6, 2023
4ffc396
newline again
rockspore Apr 6, 2023
d302af3
generate projects
rockspore Apr 6, 2023
2fbdced
add stdout logger factory
rockspore Apr 6, 2023
34c5c8d
fix includes
rockspore Apr 6, 2023
e7f4471
iwyu
rockspore Apr 6, 2023
33c569a
iwyu again
rockspore Apr 7, 2023
54ec1b9
fix header
rockspore Apr 7, 2023
0960d97
add port_platform header
rockspore Apr 7, 2023
8a29aec
Merge branch 'master' of https://github.com/grpc/grpc into xds-audit-…
rockspore Apr 7, 2023
2d00e8d
IWYU pragma
rockspore Apr 10, 2023
682c68f
add parsing in http rbac and test
rockspore Apr 10, 2023
01ce316
Merge branch 'master' of https://github.com/grpc/grpc into xds-audit-…
rockspore Apr 10, 2023
87d69b9
pull upstream to fix errors.status() call
rockspore Apr 10, 2023
c312c64
iwyu for http rbac
rockspore Apr 10, 2023
f5312ba
clang tidy
rockspore Apr 11, 2023
86a3c88
copy stream.proto into testing/
rockspore Apr 14, 2023
5fe48fa
generate projects
rockspore Apr 14, 2023
51fb0ca
IWYU pragma
rockspore Apr 14, 2023
6967b16
IWYU pragma
rockspore Apr 14, 2023
f275f0b
trailing newline
rockspore Apr 14, 2023
21bf892
comments
rockspore Apr 20, 2023
259eb25
Merge branch 'master' of github.com:grpc/grpc into xds-audit-registry
rockspore Apr 20, 2023
f17c235
new upb header
rockspore Apr 20, 2023
bb5ff41
iwyu
rockspore Apr 21, 2023
d17a2b6
address comments
rockspore Apr 24, 2023
08aa62d
remove rbac header
rockspore Apr 24, 2023
537be0d
add back rbac header
rockspore Apr 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 11 additions & 7 deletions CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion build_autogenerated.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions src/core/ext/xds/xds_audit_logger_registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ Json XdsAuditLoggerRegistry::ConvertXdsAuditLoggerConfig(
const auto* typed_extension_config =
envoy_config_rbac_v3_RBAC_AuditLoggingOptions_AuditLoggerConfig_audit_logger(
logger_config);
// It is okay if this is not present.
ValidationErrors::ScopedField field(errors, ".audit_logger");
if (typed_extension_config == nullptr) {
errors->AddError("this field is required");
markdroth marked this conversation as resolved.
Show resolved Hide resolved
return Json(); // A null Json object.
} else {
ValidationErrors::ScopedField field(errors,
".typed_extension_config.typed_config");
ValidationErrors::ScopedField field(errors, ".typed_config");
const auto* typed_config =
envoy_config_core_v3_TypedExtensionConfig_typed_config(
typed_extension_config);
Expand All @@ -84,12 +84,18 @@ Json XdsAuditLoggerRegistry::ConvertXdsAuditLoggerConfig(
auto config_factory_it =
audit_logger_config_factories_.find(extension->type);
if (config_factory_it != audit_logger_config_factories_.end()) {
gtcooke94 marked this conversation as resolved.
Show resolved Hide resolved
// TODO(lwge): Parse the config with the gRPC audit logger registry.
return config_factory_it->second->ConvertXdsAuditLoggerConfig(
markdroth marked this conversation as resolved.
Show resolved Hide resolved
context, *serialized_value, errors);
}
}
// TODO(lwge): Check for third-party audit logger type. For now, we disallow
// it by rejecting TypedStruct entries.
if (absl::get_if<Json>(&extension->value) != nullptr) {
errors->AddError("third-party audit logger is not supported");
return Json();
}
}
markdroth marked this conversation as resolved.
Show resolved Hide resolved
// TODO(lwge): Check for third-party audit logger type.
// Add validation error only if the config is not marked optional.
if (!envoy_config_rbac_v3_RBAC_AuditLoggingOptions_AuditLoggerConfig_is_optional(
logger_config)) {
Expand Down
19 changes: 15 additions & 4 deletions src/core/ext/xds/xds_http_rbac_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ Json ParseAuditLoggerConfigsToJson(
audit_logging_options, &size);
for (size_t i = 0; i < size; ++i) {
ValidationErrors::ScopedField field(
errors, absl::StrCat(".audit_logging_options.logger_configs[", i, "]"));
errors, absl::StrCat(".logger_configs[", i, "]"));
logger_configs_json.emplace_back(registry.ConvertXdsAuditLoggerConfig(
context, logger_configs[i], errors));
}
Expand Down Expand Up @@ -440,12 +440,23 @@ Json ParseHttpRbacToJson(const XdsResourceType::DecodeContext& context,
}
// Flatten the nested messages defined in rbac.proto
if (envoy_config_rbac_v3_RBAC_has_audit_logging_options(rules)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that we need env var protection for this code that looks at the new xDS fields. Can you please put together a PR to add that ASAP? I want to make sure that this PR doesn't make its way into a release branch before we have the env var protection, or else we'll have to deal with broken releases in the wild, which is a major pain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. Will work on it right now.

ValidationErrors::ScopedField field(errors, ".audit_logging_options");
const auto* audit_logging_options =
envoy_config_rbac_v3_RBAC_audit_logging_options(rules);
inner_rbac_json.emplace(
"audit_condition",
int32_t audit_condition =
envoy_config_rbac_v3_RBAC_AuditLoggingOptions_audit_condition(
markdroth marked this conversation as resolved.
Show resolved Hide resolved
audit_logging_options));
audit_logging_options);
switch (audit_condition) {
case envoy_config_rbac_v3_RBAC_AuditLoggingOptions_NONE:
case envoy_config_rbac_v3_RBAC_AuditLoggingOptions_ON_DENY:
case envoy_config_rbac_v3_RBAC_AuditLoggingOptions_ON_ALLOW:
case envoy_config_rbac_v3_RBAC_AuditLoggingOptions_ON_DENY_AND_ALLOW:
inner_rbac_json.emplace("audit_condition", audit_condition);
break;
default:
ValidationErrors::ScopedField field(errors, ".audit_condition");
errors->AddError("invalid audit condition");
}
if (envoy_config_rbac_v3_RBAC_AuditLoggingOptions_has_logger_configs(
audit_logging_options)) {
inner_rbac_json.emplace("audit_loggers",
Expand Down
4 changes: 2 additions & 2 deletions src/proto/grpc/testing/xds/v3/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,9 @@ grpc_proto_library(

# Contains stdout audit logger.
grpc_proto_library(
name = "stream_proto",
name = "audit_logger_stream_proto",
srcs = [
"stream.proto",
"audit_logger_stream.proto",
],
)

Expand Down
3 changes: 2 additions & 1 deletion test/core/xds/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,9 @@ grpc_cc_test(
deps = [
"//:gpr",
"//:grpc",
"//src/proto/grpc/testing/xds/v3:audit_logger_stream_proto",
"//src/proto/grpc/testing/xds/v3:rbac_proto",
"//src/proto/grpc/testing/xds/v3:stream_proto",
"//src/proto/grpc/testing/xds/v3:typed_struct_proto",
"//test/core/util:grpc_test_util",
"//test/cpp/util:grpc_cli_utils",
],
Expand Down
49 changes: 41 additions & 8 deletions test/core/xds/xds_audit_logger_registry_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@
#include "absl/status/statusor.h"
#include "envoy/config/rbac/v3/rbac.upb.h"
#include "gtest/gtest.h"
#include "upb/def.hpp" // IWYU pragma: keep
#include "upb/reflection/def.hpp"
#include "upb/upb.hpp"

#include <grpc/grpc.h>

#include "src/core/ext/xds/xds_bootstrap_grpc.h"
#include "src/core/lib/json/json_writer.h"
#include "src/proto/grpc/testing/xds/v3/audit_logger_stream.pb.h"
#include "src/proto/grpc/testing/xds/v3/extension.pb.h"
#include "src/proto/grpc/testing/xds/v3/rbac.pb.h"
#include "src/proto/grpc/testing/xds/v3/stream.pb.h"
#include "src/proto/grpc/testing/xds/v3/typed_struct.pb.h"
#include "test/core/util/test_config.h"

// IWYU pragma: no_include "upb/reflection/def.hpp"

namespace grpc_core {
namespace testing {
namespace {

using AuditLoggerConfigProto =
::envoy::config::rbac::v3::RBAC::AuditLoggingOptions::AuditLoggerConfig;
using ::envoy::extensions::rbac::audit_loggers::stream::v3::StdoutAuditLog;
using ::xds::type::v3::TypedStruct;

absl::StatusOr<std::string> ConvertAuditLoggerConfig(
const AuditLoggerConfigProto& config) {
Expand All @@ -60,7 +60,7 @@ absl::StatusOr<std::string> ConvertAuditLoggerConfig(
envoy_config_rbac_v3_RBAC_AuditLoggingOptions_AuditLoggerConfig_parse(
serialized_config.data(), serialized_config.size(), arena.ptr());
ValidationErrors errors;
ValidationErrors::ScopedField field(&errors, ".logger_config");
ValidationErrors::ScopedField field(&errors, ".logger_configs");
markdroth marked this conversation as resolved.
Show resolved Hide resolved
auto config_json = XdsAuditLoggerRegistry().ConvertXdsAuditLoggerConfig(
context, upb_config, &errors);
if (!errors.ok()) {
Expand All @@ -83,14 +83,36 @@ TEST(StdoutLoggerTest, Basic) {
EXPECT_EQ(*result, "{\"stdout_logger\":{}}");
}

//
// ThirdPartyLoggerTest
//

TEST(XdsAuditLoggerRegistryTest, ThirdPartyLogger) {
AuditLoggerConfigProto config;
TypedStruct logger;
logger.set_type_url("myorg/foo/bar/test.UnknownAuditLogger");
config.mutable_audit_logger()->mutable_typed_config()->PackFrom(logger);
auto result = ConvertAuditLoggerConfig(config);
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(result.status().message(),
"validation errors: "
"[field:logger_configs.audit_logger.typed_config.value"
"[xds.type.v3.TypedStruct].value[test.UnknownAuditLogger] "
"error:third-party audit logger is not supported]")
<< result.status();
}

//
// XdsAuditLoggerRegistryTest
//

TEST(XdsAuditLoggerRegistryTest, EmptyAuditLoggerConfig) {
auto result = ConvertAuditLoggerConfig(AuditLoggerConfigProto());
EXPECT_EQ(result.status().code(), absl::StatusCode::kOk);
EXPECT_EQ(*result, "null");
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(result.status().message(),
"validation errors: [field:logger_configs.audit_logger error:this "
"field is required]")
<< result.status();
}

TEST(XdsAuditLoggerRegistryTest, NoSupportedType) {
markdroth marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -100,11 +122,22 @@ TEST(XdsAuditLoggerRegistryTest, NoSupportedType) {
auto result = ConvertAuditLoggerConfig(config);
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(result.status().message(),
"validation errors: [field:logger_config error:unsupported audit "
"validation errors: [field:logger_configs.audit_logger "
"error:unsupported audit "
"logger type]")
markdroth marked this conversation as resolved.
Show resolved Hide resolved
<< result.status();
}

TEST(XdsAuditLoggerRegistryTest, NoSupportedTypeButIsOptional) {
AuditLoggerConfigProto config;
config.mutable_audit_logger()->mutable_typed_config()->PackFrom(
AuditLoggerConfigProto());
config.set_is_optional(true);
auto result = ConvertAuditLoggerConfig(config);
EXPECT_EQ(result.status().code(), absl::StatusCode::kOk);
EXPECT_EQ(*result, "null");
}

} // namespace
} // namespace testing
} // namespace grpc_core
Expand Down
33 changes: 28 additions & 5 deletions test/core/xds/xds_http_filters_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,28 @@ TEST_P(XdsRbacFilterConfigTest, AuditLoggingOptions) {
"}}");
}

TEST_P(XdsRbacFilterConfigTest, InvalidAuditCondition) {
RBAC rbac;
auto* rules = rbac.mutable_rules();
rules->set_action(rules->ALLOW);
auto* logging_options = rules->mutable_audit_logging_options();
logging_options->set_audit_condition(
static_cast<
envoy::config::rbac::v3::RBAC_AuditLoggingOptions_AuditCondition>(
100));
auto config = GenerateConfig(rbac);
absl::Status status = errors_.status(absl::StatusCode::kInvalidArgument,
"errors validating filter config");
EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(status.message(),
absl::StrCat("errors validating filter config: ["
"field:",
FieldPrefix(),
".rules.audit_logging_options.audit_condition "
"error:invalid audit condition]"))
<< status;
}

TEST_P(XdsRbacFilterConfigTest, InvalidAuditLoggerConfig) {
RBAC rbac;
auto* rules = rbac.mutable_rules();
Expand All @@ -922,11 +944,12 @@ TEST_P(XdsRbacFilterConfigTest, InvalidAuditLoggerConfig) {
"errors validating filter config");
EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
EXPECT_EQ(status.message(),
absl::StrCat("errors validating filter config: ["
"field:",
FieldPrefix(),
".rules.audit_logging_options.logger_configs[0] "
"error:unsupported audit logger type]"))
absl::StrCat(
"errors validating filter config: ["
"field:",
FieldPrefix(),
".rules.audit_logging_options.logger_configs[0].audit_logger "
"error:unsupported audit logger type]"))
<< status;
}

Expand Down