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] Logger and factory APIs in C-Core and C++. #32750

Merged
merged 53 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5f36c9b
audit logging APIs
rockspore Mar 29, 2023
1ef7536
const functions
rockspore Mar 29, 2023
d73779e
fix include guards
rockspore Mar 29, 2023
5fa99bc
move .cc to src/cpp/server
rockspore Mar 29, 2023
8a75d02
trailing newline
rockspore Mar 29, 2023
e77a037
changed the design
rockspore Mar 30, 2023
c6b1174
add register impl in C++
rockspore Mar 30, 2023
6ab33b3
remove extra include
rockspore Mar 30, 2023
c623c9e
newlines
rockspore Mar 30, 2023
3b85b67
include port_platform
rockspore Mar 30, 2023
ba8b7ae
move API headers inside for now
rockspore Apr 7, 2023
f9b7748
Merge branch 'master' of https://github.com/grpc/grpc into audit-log-api
rockspore Apr 7, 2023
eb82b4e
put current src into BUILD targets
rockspore Apr 7, 2023
c7776d3
generate projects
rockspore Apr 7, 2023
579fb6b
virtual dtors, etc
rockspore Apr 10, 2023
ccb3a0c
BUILD
rockspore Apr 10, 2023
70098a0
virtual dtors
rockspore Apr 10, 2023
b323fc8
generate projects
rockspore Apr 10, 2023
03a449a
iwyu
rockspore Apr 10, 2023
f98b12d
external deps in BUILD
rockspore Apr 10, 2023
dc3f3b8
iwyu again
rockspore Apr 10, 2023
0d2fcb5
ctor for audit context
rockspore Apr 10, 2023
07365a4
sanity check
rockspore Apr 10, 2023
c5a8598
add tests and move APIs to public headers
rockspore Apr 11, 2023
fc810a3
generate projects
rockspore Apr 11, 2023
8e8faec
fix iwyu
rockspore Apr 11, 2023
c83b7f0
remove grpc_audit_logging.h from GRPC_PUBLIC_HDRS
rockspore Apr 11, 2023
ced9d10
remove unused params
rockspore Apr 11, 2023
8f536de
remove wrapping in C++
rockspore Apr 19, 2023
f68d735
Merge branch 'master' of github.com:grpc/grpc into audit-log-api
rockspore Apr 19, 2023
81ef1ed
comments and iwyu
rockspore Apr 19, 2023
8af53a5
iwyu
rockspore Apr 19, 2023
ee874d4
add external deps to grpc_public_hdrs
rockspore Apr 20, 2023
2e575a2
comments
rockspore Apr 21, 2023
5dc1b6b
move definition into .cc
rockspore Apr 21, 2023
57c4044
make registry getter private
rockspore Apr 21, 2023
daa86a5
generate projects
rockspore Apr 21, 2023
8e5f24d
remove naked include
rockspore Apr 21, 2023
e32af2b
fix BUILD
rockspore Apr 21, 2023
930d88b
generate projects
rockspore Apr 21, 2023
8664063
fix cpp header
rockspore Apr 21, 2023
a8295ed
constexpr the register func
rockspore Apr 21, 2023
6f6acd1
no lint for unused using decls
rockspore Apr 21, 2023
127f12e
add factory existence API
rockspore Apr 21, 2023
df129cc
change registry's parsing API
rockspore Apr 21, 2023
974bb05
remove extraneous directory and file
rockspore Apr 24, 2023
d426f9d
address comments
rockspore Apr 24, 2023
06bb361
remove naked include
rockspore Apr 24, 2023
7e51701
Automated change: Fix sanity tests
rockspore Apr 24, 2023
6e4b0ec
Merge pull request #13 from rockspore/create-pull-request/patch-06bb361
rockspore Apr 24, 2023
2f3b29b
change to static members
rockspore Apr 25, 2023
dee212e
change to pointers
rockspore Apr 25, 2023
e019b5c
remove naked include
rockspore Apr 25, 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
71 changes: 71 additions & 0 deletions include/grpc/grpc_audit_logging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
//
// 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 "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"

namespace grpc_core {
namespace experimental {

// The base struct for audit context.
rockspore marked this conversation as resolved.
Show resolved Hide resolved
typedef struct CoreAuditContext {
Copy link
Member

Choose a reason for hiding this comment

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

class AuditContext { -- no need for a typedef

public:
absl::string_view rpc_method() const;
absl::string_view principal() const;
absl::string_view policy_name() const;
absl::string_view matched_rule() const;
bool authorized() const;
} AuditContext;

// This base class for audit logger implementations.
class CoreAuditLogger {
public:
virtual void CoreLog(const CoreAuditContext& audit_context) = 0;
Copy link
Member

Choose a reason for hiding this comment

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

This should just be Log(...), and we'll have an instance that has a unique_ptr<grpc::AuditLogger> log_ that we call log_->Log(...) on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So it means this class defined in C-Core can have a dependence on the C++ class, right? I initially was about to do this but wasn't sure if it's fine to have such a reversed dependency.

Copy link
Contributor Author

@rockspore rockspore Mar 30, 2023

Choose a reason for hiding this comment

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

Oh. is the following flow correct?

// C-Core
class AuditLogger {
 public:
  virtual void Log() = 0;
};
// C++
class AuditLogger {
 public:
  virtual void Log() = 0;
};

class AuditLoggerFactory {
 public:
  virtual std::unique_ptr<AuditLogger> CreateAuditLogger() = 0;
  std::unique_ptr<CoreLogger> CreateCoreLogger() {
    return std::make_unique<CoreLogger>(CreateAuditLogger());
  }
};

// non-public API
class CoreLogger : public grpc_core::AuditLogger {
 public:
  CoreLogger(std::unique_ptr<AuditLogger> logger) : logger_(logger) {}
  void Log() { logger_->Log(); }
 private:
  std::unique_ptr<AuditLogger> logger_;
};

};

// This is the base class for audit logger factory implementations.
class CoreAuditLoggerFactory {
public:
class CoreConfig {
public:
virtual const char* core_name() const = 0;
virtual std::string CoreToString() = 0;
};
virtual const char* core_name() const = 0;

// TODO(lwge): change to grpc_core::Json once it's exposed.
virtual absl::StatusOr<std::unique_ptr<CoreConfig>>
ParseCoreAuditLoggerConfig(absl::string_view config_json) = 0;

virtual std::unique_ptr<CoreAuditLogger> CreateCoreAuditLogger(
std::unique_ptr<CoreAuditLoggerFactory::CoreConfig>) = 0;
};

// Registers an audit logger factory. This should only be called during
// initialization.
void RegisterAuditLoggerFactory(
std::unique_ptr<CoreAuditLoggerFactory> factory);

} // namespace experimental
} // namespace grpc_core

#endif /* GRPC_GRPC_AUDIT_LOGGING_H */
106 changes: 106 additions & 0 deletions include/grpcpp/security/audit_logging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
//
// 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 <grpc/grpc_audit_logging.h>
#include <grpcpp/support/string_ref.h>

namespace grpc {
namespace experimental {

// This class contains useful information to be consumed in an audit logging
// event.
class AuditContext {
public:
// Does not take the ownership of core_context. Callers have to ensure it
// outlives this class.
explicit AuditContext(
const grpc_core::experimental::CoreAuditContext* core_context)
: core_context_(core_context) {}

grpc::string_ref rpc_method() const;
grpc::string_ref principal() const;
grpc::string_ref policy_name() const;
grpc::string_ref matched_rule() const;
bool authorized() const;

private:
const grpc_core::experimental::CoreAuditContext* core_context_;
Copy link
Member

Choose a reason for hiding this comment

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

I'd make this a reference

};

// The base class for audit logger implementations.
// Users are expected to inherit this class and implement the Log() function.
class AuditLogger : public grpc_core::experimental::CoreAuditLogger {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need inheritance here: this should be its own type.

public:
// This function will be invoked synchronously when applicable during the
// RBAC-based authorization process. It does not return anything and thus will
// not impact whether the RPC will be rejected or not.
virtual void Log(const AuditContext& audit_context) = 0;

void CoreLog(const grpc_core::experimental::CoreAuditContext&) final;
};

// The base class for audit logger factory implementations.
// Users should inherit this class and implement those declared virtual
// funcitons.
class AuditLoggerFactory
: public grpc_core::experimental::CoreAuditLoggerFactory {
Copy link
Member

Choose a reason for hiding this comment

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

No inheritance here.

public:
// The base class for the audit logger config that the factory parses.
// Users should inherit this class to define the configuration needed for
// their custom loggers.
class Config
: public grpc_core::experimental::CoreAuditLoggerFactory::CoreConfig {
public:
virtual const char* name() const = 0;
virtual std::string ToString() = 0;

const char* core_name() const final;
std::string CoreToString() final;
};
virtual const char* name() const = 0;

virtual absl::StatusOr<std::unique_ptr<Config>> ParseAuditLoggerConfig(
grpc::string_ref config_json) = 0;

virtual std::unique_ptr<AuditLogger> CreateAuditLogger(
std::unique_ptr<AuditLoggerFactory::Config>) = 0;

const char* core_name() const final;

absl::StatusOr<std::unique_ptr<
grpc_core::experimental::CoreAuditLoggerFactory::CoreConfig>>
ParseCoreAuditLoggerConfig(absl::string_view config_json) final;

std::unique_ptr<grpc_core::experimental::CoreAuditLogger>
CreateCoreAuditLogger(
std::unique_ptr<
grpc_core::experimental::CoreAuditLoggerFactory::CoreConfig>)
final;
};

// Registers an audit logger factory. This should only be called during
// initialization.
void RegisterAuditLoggerFactory(std::unique_ptr<AuditLoggerFactory> factory);
rockspore marked this conversation as resolved.
Show resolved Hide resolved

} // namespace experimental
} // namespace grpc

#endif // GRPCPP_SECURITY_AUDIT_LOGGING_H
88 changes: 88 additions & 0 deletions src/cpp/server/audit_logging.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
//
// 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 <memory>

#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"

#include <grpc/grpc_audit_logging.h>
#include <grpcpp/security/audit_logging.h>
#include <grpcpp/support/string_ref.h>

namespace grpc {
namespace experimental {

using grpc_core::experimental::CoreAuditContext;
using grpc_core::experimental::CoreAuditLogger;
using grpc_core::experimental::CoreAuditLoggerFactory;

grpc::string_ref AuditContext::rpc_method() const {
absl::string_view s = core_context_->rpc_method();
return grpc::string_ref(s.data(), s.length());
}

grpc::string_ref AuditContext::principal() const {
absl::string_view s = core_context_->principal();
return grpc::string_ref(s.data(), s.length());
}

grpc::string_ref AuditContext::policy_name() const {
absl::string_view s = core_context_->policy_name();
return grpc::string_ref(s.data(), s.length());
}

grpc::string_ref AuditContext::matched_rule() const {
absl::string_view s = core_context_->matched_rule();
return grpc::string_ref(s.data(), s.length());
}

bool AuditContext::authorized() const { return core_context_->authorized(); }

void AuditLogger::CoreLog(const CoreAuditContext& core_audit_context) {
AuditContext audit_context(&core_audit_context);
Log(audit_context);
}

const char* AuditLoggerFactory::Config::core_name() const { return name(); }

std::string AuditLoggerFactory::Config::CoreToString() { return ToString(); }

const char* AuditLoggerFactory::core_name() const { return name(); }

absl::StatusOr<std::unique_ptr<CoreAuditLoggerFactory::CoreConfig>>
AuditLoggerFactory::ParseCoreAuditLoggerConfig(absl::string_view config_json) {
grpc::string_ref config(config_json.data(), config_json.length());
return ParseAuditLoggerConfig(config);
}

std::unique_ptr<CoreAuditLogger> AuditLoggerFactory::CreateCoreAuditLogger(
std::unique_ptr<CoreAuditLoggerFactory::CoreConfig> config) {
std::unique_ptr<AuditLoggerFactory::Config> c(
static_cast<AuditLoggerFactory::Config*>(config.release()));
return CreateAuditLogger(std::move(c));
}

void RegisterAuditLoggerFactory(std::unique_ptr<AuditLoggerFactory> factory) {
std::unique_ptr<CoreAuditLoggerFactory> core_factory(
static_cast<CoreAuditLoggerFactory*>(factory.release()));
grpc_core::experimental::RegisterAuditLoggerFactory(std::move(core_factory));
};

} // namespace experimental
} // namespace grpc