diff --git a/BUILD b/BUILD index 0ec885e7cf6..6360a23b29c 100644 --- a/BUILD +++ b/BUILD @@ -220,6 +220,7 @@ GPR_PUBLIC_HDRS = [ ] GRPC_PUBLIC_HDRS = [ + "include/grpc/grpc_audit_logging.h", "include/grpc/byte_buffer.h", "include/grpc/byte_buffer_reader.h", "include/grpc/compression.h", @@ -388,6 +389,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/status.h", "include/grpcpp/impl/sync.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/security/audit_logging.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", @@ -790,6 +792,10 @@ grpc_cc_library( grpc_cc_library( name = "grpc_public_hdrs", hdrs = GRPC_PUBLIC_HDRS, + external_deps = [ + "absl/status:statusor", + "absl/strings", + ], tags = [ "avoid_dep", "nofixdeps", @@ -1734,6 +1740,7 @@ grpc_cc_library( "//src/core:handshaker_factory", "//src/core:handshaker_registry", "//src/core:iomgr_fwd", + "//src/core:json", "//src/core:memory_quota", "//src/core:poll", "//src/core:ref_counted", @@ -1886,6 +1893,7 @@ grpc_cc_library( "//src/core:error", "//src/core:gpr_atm", "//src/core:gpr_manual_constructor", + "//src/core:grpc_audit_logging", "//src/core:grpc_backend_metric_provider", "//src/core:grpc_service_config", "//src/core:grpc_transport_inproc", diff --git a/CMakeLists.txt b/CMakeLists.txt index f053c6cd3e9..c4ba60ab802 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -982,6 +982,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx google_mesh_ca_certificate_provider_factory_test) add_dependencies(buildtests_cxx graceful_shutdown_test) add_dependencies(buildtests_cxx grpc_alts_credentials_options_test) + add_dependencies(buildtests_cxx grpc_audit_logging_test) add_dependencies(buildtests_cxx grpc_authorization_engine_test) add_dependencies(buildtests_cxx grpc_authorization_policy_provider_test) add_dependencies(buildtests_cxx grpc_authz_end2end_test) @@ -2409,6 +2410,7 @@ foreach(_hdr include/grpc/event_engine/slice_buffer.h include/grpc/fork.h include/grpc/grpc.h + include/grpc/grpc_audit_logging.h include/grpc/grpc_posix.h include/grpc/grpc_security.h include/grpc/grpc_security_constants.h @@ -3043,6 +3045,7 @@ foreach(_hdr include/grpc/event_engine/slice_buffer.h include/grpc/fork.h include/grpc/grpc.h + include/grpc/grpc_audit_logging.h include/grpc/grpc_posix.h include/grpc/grpc_security.h include/grpc/grpc_security_constants.h @@ -3219,6 +3222,7 @@ add_library(grpc++ src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc @@ -3472,6 +3476,7 @@ foreach(_hdr include/grpcpp/impl/status.h include/grpcpp/impl/sync.h include/grpcpp/resource_quota.h + include/grpcpp/security/audit_logging.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/authorization_policy_provider.h @@ -4175,6 +4180,7 @@ foreach(_hdr include/grpcpp/impl/status.h include/grpcpp/impl/sync.h include/grpcpp/resource_quota.h + include/grpcpp/security/audit_logging.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/authorization_policy_provider.h @@ -4545,6 +4551,7 @@ foreach(_hdr include/grpc/event_engine/slice_buffer.h include/grpc/fork.h include/grpc/grpc.h + include/grpc/grpc_audit_logging.h include/grpc/grpc_posix.h include/grpc/grpc_security.h include/grpc/grpc_security_constants.h @@ -6846,6 +6853,7 @@ add_executable(binder_transport_test src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc @@ -9918,6 +9926,7 @@ add_executable(endpoint_binder_pool_test src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc @@ -10610,6 +10619,7 @@ add_executable(fake_binder_test src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc @@ -11944,6 +11954,44 @@ target_link_libraries(grpc_alts_credentials_options_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(grpc_audit_logging_test + src/core/lib/security/authorization/audit_logging.cc + test/core/security/grpc_audit_logging_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(grpc_audit_logging_test PUBLIC cxx_std_14) +target_include_directories(grpc_audit_logging_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_audit_logging_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) @@ -21782,6 +21830,7 @@ add_executable(transport_stream_receiver_test src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc @@ -22496,6 +22545,7 @@ add_executable(wire_reader_test src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc @@ -22597,6 +22647,7 @@ add_executable(wire_writer_test src/core/ext/transport/binder/wire_format/transaction.cc src/core/ext/transport/binder/wire_format/wire_reader_impl.cc src/core/ext/transport/binder/wire_format/wire_writer.cc + src/core/lib/security/authorization/audit_logging.cc src/cpp/client/channel_cc.cc src/cpp/client/client_callback.cc src/cpp/client/client_context.cc diff --git a/Makefile b/Makefile index ee502e798ce..780ab2f7512 100644 --- a/Makefile +++ b/Makefile @@ -1733,6 +1733,7 @@ PUBLIC_HEADERS_C += \ include/grpc/event_engine/slice_buffer.h \ include/grpc/fork.h \ include/grpc/grpc.h \ + include/grpc/grpc_audit_logging.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ @@ -2222,6 +2223,7 @@ PUBLIC_HEADERS_C += \ include/grpc/event_engine/slice_buffer.h \ include/grpc/fork.h \ include/grpc/grpc.h \ + include/grpc/grpc_audit_logging.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index b56bb00b125..7c0a370b73e 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -155,6 +155,7 @@ libs: - include/grpc/event_engine/slice_buffer.h - include/grpc/fork.h - include/grpc/grpc.h + - include/grpc/grpc_audit_logging.h - include/grpc/grpc_posix.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h @@ -1847,6 +1848,7 @@ libs: - include/grpc/event_engine/slice_buffer.h - include/grpc/fork.h - include/grpc/grpc.h + - include/grpc/grpc_audit_logging.h - include/grpc/grpc_posix.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h @@ -2896,6 +2898,7 @@ libs: - include/grpcpp/impl/status.h - include/grpcpp/impl/sync.h - include/grpcpp/resource_quota.h + - include/grpcpp/security/audit_logging.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/authorization_policy_provider.h @@ -2957,6 +2960,7 @@ libs: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -2988,6 +2992,7 @@ libs: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc @@ -3318,6 +3323,7 @@ libs: - include/grpcpp/impl/status.h - include/grpcpp/impl/sync.h - include/grpcpp/resource_quota.h + - include/grpcpp/security/audit_logging.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/authorization_policy_provider.h @@ -3424,6 +3430,7 @@ libs: - include/grpc/event_engine/slice_buffer.h - include/grpc/fork.h - include/grpc/grpc.h + - include/grpc/grpc_audit_logging.h - include/grpc/grpc_posix.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h @@ -4972,6 +4979,7 @@ targets: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -5004,6 +5012,7 @@ targets: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc @@ -6450,6 +6459,7 @@ targets: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -6482,6 +6492,7 @@ targets: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc @@ -6872,6 +6883,7 @@ targets: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -6904,6 +6916,7 @@ targets: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc @@ -7991,6 +8004,17 @@ targets: - test/core/util/tracer_util.cc deps: - grpc_test_util +- name: grpc_audit_logging_test + gtest: true + build: test + language: c++ + headers: + - src/core/lib/security/authorization/audit_logging.h + src: + - src/core/lib/security/authorization/audit_logging.cc + - test/core/security/grpc_audit_logging_test.cc + deps: + - grpc_test_util - name: grpc_authorization_engine_test gtest: true build: test @@ -12250,6 +12274,7 @@ targets: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -12281,6 +12306,7 @@ targets: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc @@ -12563,6 +12589,7 @@ targets: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -12595,6 +12622,7 @@ targets: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc @@ -12670,6 +12698,7 @@ targets: - src/core/ext/transport/binder/wire_format/wire_reader.h - src/core/ext/transport/binder/wire_format/wire_reader_impl.h - src/core/ext/transport/binder/wire_format/wire_writer.h + - src/core/lib/security/authorization/audit_logging.h - src/cpp/client/client_stats_interceptor.h - src/cpp/client/create_channel_internal.h - src/cpp/client/secure_credentials.h @@ -12702,6 +12731,7 @@ targets: - src/core/ext/transport/binder/wire_format/transaction.cc - src/core/ext/transport/binder/wire_format/wire_reader_impl.cc - src/core/ext/transport/binder/wire_format/wire_writer.cc + - src/core/lib/security/authorization/audit_logging.cc - src/cpp/client/channel_cc.cc - src/cpp/client/client_callback.cc - src/cpp/client/client_context.cc diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index baa92041f0a..c2312e2d4da 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -167,6 +167,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/status.h', 'include/grpcpp/impl/sync.h', 'include/grpcpp/resource_quota.h', + 'include/grpcpp/security/audit_logging.h', 'include/grpcpp/security/auth_context.h', 'include/grpcpp/security/auth_metadata_processor.h', 'include/grpcpp/security/authorization_policy_provider.h', @@ -957,6 +958,8 @@ Pod::Spec.new do |s| 'src/core/lib/resource_quota/resource_quota.h', 'src/core/lib/resource_quota/thread_quota.h', 'src/core/lib/resource_quota/trace.h', + 'src/core/lib/security/authorization/audit_logging.cc', + 'src/core/lib/security/authorization/audit_logging.h', 'src/core/lib/security/authorization/authorization_engine.h', 'src/core/lib/security/authorization/authorization_policy_provider.h', 'src/core/lib/security/authorization/evaluate_args.h', @@ -1982,6 +1985,7 @@ Pod::Spec.new do |s| 'src/core/lib/resource_quota/resource_quota.h', 'src/core/lib/resource_quota/thread_quota.h', 'src/core/lib/resource_quota/trace.h', + 'src/core/lib/security/authorization/audit_logging.h', 'src/core/lib/security/authorization/authorization_engine.h', 'src/core/lib/security/authorization/authorization_policy_provider.h', 'src/core/lib/security/authorization/evaluate_args.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index b84f9b4be72..593c3b7b33d 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -122,6 +122,7 @@ Pod::Spec.new do |s| 'include/grpc/event_engine/slice_buffer.h', 'include/grpc/fork.h', 'include/grpc/grpc.h', + 'include/grpc/grpc_audit_logging.h', 'include/grpc/grpc_posix.h', 'include/grpc/grpc_security.h', 'include/grpc/grpc_security_constants.h', diff --git a/grpc.gemspec b/grpc.gemspec index 2bcf9a873a8..2761e4867e1 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -62,6 +62,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/event_engine/slice_buffer.h ) s.files += %w( include/grpc/fork.h ) s.files += %w( include/grpc/grpc.h ) + s.files += %w( include/grpc/grpc_audit_logging.h ) s.files += %w( include/grpc/grpc_posix.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security_constants.h ) diff --git a/grpc.gyp b/grpc.gyp index 8c736e6704c..de1ac9d2dd3 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -1506,6 +1506,7 @@ 'src/core/ext/transport/binder/wire_format/transaction.cc', 'src/core/ext/transport/binder/wire_format/wire_reader_impl.cc', 'src/core/ext/transport/binder/wire_format/wire_writer.cc', + 'src/core/lib/security/authorization/audit_logging.cc', 'src/cpp/client/channel_cc.cc', 'src/cpp/client/client_callback.cc', 'src/cpp/client/client_context.cc', diff --git a/include/grpc/grpc_audit_logging.h b/include/grpc/grpc_audit_logging.h new file mode 100644 index 00000000000..a74ba8fd775 --- /dev/null +++ b/include/grpc/grpc_audit_logging.h @@ -0,0 +1,96 @@ +// +// +// Copyright 2023 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_GRPC_AUDIT_LOGGING_H +#define GRPC_GRPC_AUDIT_LOGGING_H + +#include + +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +// TODO(lwge): Switch to public header when it's ready. +#include "src/core/lib/json/json.h" + +namespace grpc_core { +namespace experimental { + +// The class containing the context for an audited RPC. +class AuditContext { + public: + AuditContext(absl::string_view rpc_method, absl::string_view principal, + absl::string_view policy_name, absl::string_view matched_rule, + bool authorized) + : rpc_method_(rpc_method), + principal_(principal), + policy_name_(policy_name), + matched_rule_(matched_rule), + authorized_(authorized) {} + + absl::string_view rpc_method() const { return rpc_method_; } + absl::string_view principal() const { return principal_; } + absl::string_view policy_name() const { return policy_name_; } + absl::string_view matched_rule() const { return matched_rule_; } + bool authorized() const { return authorized_; } + + private: + absl::string_view rpc_method_; + absl::string_view principal_; + absl::string_view policy_name_; + absl::string_view matched_rule_; + bool authorized_; +}; + +// This base class for audit logger implementations. +class AuditLogger { + public: + virtual ~AuditLogger() = default; + virtual void Log(const AuditContext& audit_context) = 0; +}; + +// This is the base class for audit logger factory implementations. +class AuditLoggerFactory { + public: + class Config { + public: + virtual ~Config() = default; + virtual absl::string_view name() const = 0; + virtual std::string ToString() const = 0; + }; + + virtual ~AuditLoggerFactory() = default; + virtual absl::string_view name() const = 0; + + virtual absl::StatusOr> ParseAuditLoggerConfig( + const Json& json) = 0; + + virtual std::unique_ptr CreateAuditLogger( + std::unique_ptr) = 0; +}; + +// Registers an audit logger factory. This should only be called during +// initialization. +void RegisterAuditLoggerFactory(std::unique_ptr factory); + +} // namespace experimental +} // namespace grpc_core + +#endif /* GRPC_GRPC_AUDIT_LOGGING_H */ diff --git a/include/grpc/module.modulemap b/include/grpc/module.modulemap index 31685d2ec7e..49c3c3dfddf 100644 --- a/include/grpc/module.modulemap +++ b/include/grpc/module.modulemap @@ -8,6 +8,7 @@ header "byte_buffer.h" header "compression.h" header "fork.h" header "grpc.h" + header "grpc_audit_logging.h" header "grpc_posix.h" header "grpc_security.h" header "grpc_security_constants.h" diff --git a/include/grpcpp/security/audit_logging.h b/include/grpcpp/security/audit_logging.h new file mode 100644 index 00000000000..b29464a6907 --- /dev/null +++ b/include/grpcpp/security/audit_logging.h @@ -0,0 +1,44 @@ +// +// +// Copyright 2023 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 GRPCPP_SECURITY_AUDIT_LOGGING_H +#define GRPCPP_SECURITY_AUDIT_LOGGING_H + +#include +#include +#include + +#include "absl/status/statusor.h" + +#include +#include + +namespace grpc { +namespace experimental { + +using grpc_core::experimental::AuditContext; // NOLINT(misc-unused-using-decls) +using grpc_core::experimental::AuditLogger; // NOLINT(misc-unused-using-decls) +using grpc_core::experimental:: + AuditLoggerFactory; // NOLINT(misc-unused-using-decls) +using grpc_core::experimental:: + RegisterAuditLoggerFactory; // NOLINT(misc-unused-using-decls) + +} // namespace experimental +} // namespace grpc + +#endif // GRPCPP_SECURITY_AUDIT_LOGGING_H diff --git a/package.xml b/package.xml index d8823119515..887fe771a4a 100644 --- a/package.xml +++ b/package.xml @@ -44,6 +44,7 @@ + diff --git a/src/core/BUILD b/src/core/BUILD index ce7b6054e9c..d3553854041 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -2716,6 +2716,28 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc_audit_logging", + srcs = [ + "lib/security/authorization/audit_logging.cc", + ], + hdrs = [ + "lib/security/authorization/audit_logging.h", + ], + external_deps = [ + "absl/base:core_headers", + "absl/status", + "absl/status:statusor", + "absl/strings", + "absl/strings:str_format", + ], + deps = [ + "json", + "//:gpr", + "//:grpc_base", + ], +) + grpc_cc_library( name = "grpc_authorization_base", srcs = [ diff --git a/src/core/lib/security/authorization/audit_logging.cc b/src/core/lib/security/authorization/audit_logging.cc new file mode 100644 index 00000000000..2be619fff1e --- /dev/null +++ b/src/core/lib/security/authorization/audit_logging.cc @@ -0,0 +1,91 @@ +// +// +// Copyright 2023 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 + +#include "src/core/lib/security/authorization/audit_logging.h" + +#include +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" + +#include +#include + +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/json/json.h" + +namespace grpc_core { +namespace experimental { + +Mutex* AuditLoggerRegistry::mu = new Mutex(); + +AuditLoggerRegistry* AuditLoggerRegistry::registry = new AuditLoggerRegistry(); + +void AuditLoggerRegistry::RegisterFactory( + std::unique_ptr factory) { + GPR_ASSERT(factory != nullptr); + MutexLock lock(mu); + absl::string_view name = factory->name(); + GPR_ASSERT( + registry->logger_factories_map_.emplace(name, std::move(factory)).second); +} + +bool AuditLoggerRegistry::FactoryExists(absl::string_view name) { + MutexLock lock(mu); + return registry->logger_factories_map_.find(name) != + registry->logger_factories_map_.end(); +} + +absl::StatusOr> +AuditLoggerRegistry::ParseConfig(absl::string_view name, const Json& json) { + MutexLock lock(mu); + auto it = registry->logger_factories_map_.find(name); + if (it == registry->logger_factories_map_.end()) { + return absl::NotFoundError( + absl::StrFormat("audit logger factory for %s does not exist", name)); + } + return it->second->ParseAuditLoggerConfig(json); +} + +std::unique_ptr AuditLoggerRegistry::CreateAuditLogger( + std::unique_ptr config) { + MutexLock lock(mu); + auto it = registry->logger_factories_map_.find(config->name()); + GPR_ASSERT(it != registry->logger_factories_map_.end()); + return it->second->CreateAuditLogger(std::move(config)); +} + +void AuditLoggerRegistry::TestOnlyResetRegistry() { + MutexLock lock(mu); + delete registry; + registry = new AuditLoggerRegistry(); +} + +void RegisterAuditLoggerFactory(std::unique_ptr factory) { + AuditLoggerRegistry::RegisterFactory(std::move(factory)); +} + +} // namespace experimental +} // namespace grpc_core diff --git a/src/core/lib/security/authorization/audit_logging.h b/src/core/lib/security/authorization/audit_logging.h new file mode 100644 index 00000000000..55087b0a5d6 --- /dev/null +++ b/src/core/lib/security/authorization/audit_logging.h @@ -0,0 +1,74 @@ +// +// +// Copyright 2023 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_SRC_CORE_LIB_SECURITY_AUTHORIZATION_AUDIT_LOGGING_H +#define GRPC_SRC_CORE_LIB_SECURITY_AUTHORIZATION_AUDIT_LOGGING_H + +#include + +#include +#include + +#include "absl/base/thread_annotations.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +#include + +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/json/json.h" + +namespace grpc_core { +namespace experimental { + +class AuditLoggerRegistry { + public: + static void RegisterFactory(std::unique_ptr); + + static bool FactoryExists(absl::string_view name); + + static absl::StatusOr> + ParseConfig(absl::string_view name, const Json& json); + + // This assume the given config is parsed and validated already. + // Therefore, it should always succeed in creating a logger. + static std::unique_ptr CreateAuditLogger( + std::unique_ptr); + + // Factories are registered during initialization. They should never be + // unregistered since they will be looked up at any time till the program + // exits. This function should only be used in tests to clear the registry. + static void TestOnlyResetRegistry(); + + private: + // TODO(lwge): Add built-in logger registrations once avaialble. + AuditLoggerRegistry() = default; + + static Mutex* mu; + + static AuditLoggerRegistry* registry ABSL_GUARDED_BY(mu); + + // The key is owned by the factory. + std::map> + logger_factories_map_ ABSL_GUARDED_BY(mu); +}; + +} // namespace experimental +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_LIB_SECURITY_AUTHORIZATION_AUDIT_LOGGING_H diff --git a/test/core/security/BUILD b/test/core/security/BUILD index f45cf407785..552340a1405 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -559,3 +559,16 @@ grpc_cc_test( "//test/core/util:grpc_test_util", ], ) + +grpc_cc_test( + name = "grpc_audit_logging_test", + srcs = ["grpc_audit_logging_test.cc"], + external_deps = ["gtest"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//src/core:grpc_audit_logging", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/security/grpc_audit_logging_test.cc b/test/core/security/grpc_audit_logging_test.cc new file mode 100644 index 00000000000..9fd45fa0309 --- /dev/null +++ b/test/core/security/grpc_audit_logging_test.cc @@ -0,0 +1,114 @@ +// +// +// Copyright 2023 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 + +#include +#include + +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +#include + +#include "src/core/lib/json/json.h" +#include "src/core/lib/security/authorization/audit_logging.h" +#include "test/core/util/test_config.h" +#include "test/core/util/tls_utils.h" + +namespace grpc_core { +namespace testing { + +constexpr absl::string_view kName = "test_logger"; + +using experimental::AuditContext; +using experimental::AuditLogger; +using experimental::AuditLoggerFactory; +using experimental::AuditLoggerRegistry; +using experimental::RegisterAuditLoggerFactory; + +namespace { + +class TestAuditLogger : public AuditLogger { + public: + void Log(const AuditContext&) override {} +}; + +class TestAuditLoggerFactory : public AuditLoggerFactory { + public: + class TestConfig : public Config { + public: + absl::string_view name() const override { return kName; } + std::string ToString() const override { return "test_config"; } + }; + + absl::string_view name() const override { return kName; } + std::unique_ptr CreateAuditLogger( + std::unique_ptr) override { + return std::make_unique(); + } + absl::StatusOr> ParseAuditLoggerConfig( + const Json&) override { + return std::make_unique(); + } +}; + +class AuditLoggingTest : public ::testing::Test { + protected: + void SetUp() override { + RegisterAuditLoggerFactory(std::make_unique()); + } + void TearDown() override { AuditLoggerRegistry::TestOnlyResetRegistry(); } +}; + +} // namespace + +TEST_F(AuditLoggingTest, SuccessfulLoggerCreation) { + auto result = AuditLoggerRegistry::ParseConfig(kName, Json()); + ASSERT_TRUE(result.ok()); + ASSERT_NE(AuditLoggerRegistry::CreateAuditLogger(std::move(result.value())), + nullptr); +} + +TEST_F(AuditLoggingTest, UnknownLogger) { + auto result = AuditLoggerRegistry::ParseConfig("unknown_logger", Json()); + EXPECT_EQ(result.status().code(), absl::StatusCode::kNotFound); + EXPECT_EQ(result.status().message(), + "audit logger factory for unknown_logger does not exist") + << result.status(); +} + +TEST_F(AuditLoggingTest, AuditLoggerFactoryExistenceChecks) { + EXPECT_TRUE(AuditLoggerRegistry::FactoryExists(kName)); + EXPECT_FALSE(AuditLoggerRegistry::FactoryExists("unknown_logger")); +} + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(&argc, argv); + ::testing::InitGoogleTest(&argc, argv); + grpc_init(); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index b3bb9efe921..c161f81df10 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -890,6 +890,7 @@ include/grpc/event_engine/slice.h \ include/grpc/event_engine/slice_buffer.h \ include/grpc/fork.h \ include/grpc/grpc.h \ +include/grpc/grpc_audit_logging.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ @@ -1032,6 +1033,7 @@ include/grpcpp/impl/service_type.h \ include/grpcpp/impl/status.h \ include/grpcpp/impl/sync.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/security/audit_logging.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/authorization_policy_provider.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 859ff20bc83..15b4b2ba33d 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -890,6 +890,7 @@ include/grpc/event_engine/slice.h \ include/grpc/event_engine/slice_buffer.h \ include/grpc/fork.h \ include/grpc/grpc.h \ +include/grpc/grpc_audit_logging.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ @@ -1032,6 +1033,7 @@ include/grpcpp/impl/service_type.h \ include/grpcpp/impl/status.h \ include/grpcpp/impl/sync.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/security/audit_logging.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/authorization_policy_provider.h \ @@ -2452,6 +2454,8 @@ src/core/lib/resource_quota/thread_quota.cc \ src/core/lib/resource_quota/thread_quota.h \ src/core/lib/resource_quota/trace.cc \ src/core/lib/resource_quota/trace.h \ +src/core/lib/security/authorization/audit_logging.cc \ +src/core/lib/security/authorization/audit_logging.h \ src/core/lib/security/authorization/authorization_engine.h \ src/core/lib/security/authorization/authorization_policy_provider.h \ src/core/lib/security/authorization/authorization_policy_provider_vtable.cc \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index fbc7dfe5377..f7952437ff8 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -823,6 +823,7 @@ include/grpc/event_engine/slice.h \ include/grpc/event_engine/slice_buffer.h \ include/grpc/fork.h \ include/grpc/grpc.h \ +include/grpc/grpc_audit_logging.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index cedd66f8d19..8d35ed943cc 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -823,6 +823,7 @@ include/grpc/event_engine/slice.h \ include/grpc/event_engine/slice_buffer.h \ include/grpc/fork.h \ include/grpc/grpc.h \ +include/grpc/grpc_audit_logging.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index e25e503fbc3..932383ca957 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3317,6 +3317,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_audit_logging_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false,