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 e2e test for audit logging. #33252

Merged
merged 7 commits into from May 26, 2023

Conversation

rockspore
Copy link
Contributor

Added tests involve:

  1. Checking the # of logger invocations with multiple RBACs in the chain.
  2. Verifying content in audit context with action and audit condition permutations.
  3. Confirm custom logger and built-in logger configurations are working.
  4. Confirm the feature is protected by the environment variable.

Copy link
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

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

This looks good! Comments are minor; feel free to merge after addressing.

@@ -135,6 +147,19 @@ class XdsTestType {
} else if (rbac_action_ == ::envoy::config::rbac::v3::RBAC_Action_DENY) {
retval += "RbacDeny";
}
if (rbac_audit_condition_ ==
Copy link
Member

Choose a reason for hiding this comment

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

I think you could write this a bit more easily using the protobuf method to stringify the enum element:

https://protobuf.dev/reference/cpp/cpp-generated/#enum

So you should be able to do something like this:

if (rbac_audit_condition_ !=
    ::envoy::config::rbac::v3::
            RBAC_AuditLoggingOptions_AuditCondition_NONE) {
  retval += absl::StrCat(
      "AuditCondition",
      ::envoy::config::rbac::v3::
          RBAC_AuditLoggingOptions_AuditCondition_Name(
              rbac_audit_condition_));
}

[this]() { return CreateInsecureChannel(); }, {}, {},
/*test_expects_failure=*/GetParam().rbac_action() == RBAC_Action_ALLOW,
grpc::StatusCode::PERMISSION_DENIED);
EXPECT_TRUE(audit_logs_.empty());
Copy link
Member

Choose a reason for hiding this comment

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

Suggest writing this as EXPECT_THAT(audit_logs_, ::testing::ElementsAre()), so that there's a more useful error message if the expectation fails.

Same thing in all tests.

RBAC rbac;
rbac.mutable_rules()->set_action(GetParam().rbac_action());
auto* logging_options = rbac.mutable_rules()->mutable_audit_logging_options();
envoy::config::rbac::v3::RBAC_AuditLoggingOptions::AuditLoggerConfig
Copy link
Member

Choose a reason for hiding this comment

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

Suggest writing this as:

auto* audit_logger = logging_options->add_logger_configs()->mutable_audit_logger();

Then you don't need the test_logger variable at all, nor do you need to copy it into place later.

Same thing in all tests.

@@ -2102,6 +2128,34 @@ TEST_P(XdsRbacTestWithActionPermutations, EmptyRbacPolicy) {
grpc::StatusCode::PERMISSION_DENIED);
}

TEST_P(XdsRbacTestWithActionPermutations,
Copy link
Member

Choose a reason for hiding this comment

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

Please move all of the new tests in this suite down to line 2978, so that all of the audit logging tests are after all of the tests that cover the actual authorization flow.

grpc::StatusCode::PERMISSION_DENIED);
// If the second rbac denies the rpc, only one log from the first rbac.
// Otherwise, all three rbacs log.
EXPECT_EQ(audit_logs_.size(),
Copy link
Member

Choose a reason for hiding this comment

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

Let's actually check the values here, not just the size. Note that you can construct a vector of strings however you want and then compare it with ::testing::ElementsAreArray().

Same thing for all tests.

grpc::StatusCode::PERMISSION_DENIED);
// If the second rbac denies the request, the last rbac won't log. Otherwise
// all rbacs log.
if (GetParam().rbac_action() == RBAC_Action_DENY) {
Copy link
Member

Choose a reason for hiding this comment

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

When I suggested using ElementsAreArray(), I meant something like this:

std::vector<absl::string_view> expected = {
    "{\"authorized\":true,\"matched_rule\":\"policy\","
    "\"policy_name\":\"rbac1\",\"principal\":\"\",\"rpc_"
    "method\":\"/grpc.testing.EchoTestService/Echo\"}"
};
if (GetParam().rbac_action() == RBAC_Action_DENY) {
  expected.push_back(
      "{\"authorized\":false,\"matched_rule\":\"policy\","
      "\"policy_name\":\"rbac1\",\"principal\":\"\",\"rpc_"
      "method\":\"/grpc.testing.EchoTestService/Echo\"}");
} else {
  expected.push_back(
      "{\"authorized\":true,\"matched_rule\":\"policy\","
      "\"policy_name\":\"rbac1\",\"principal\":\"\",\"rpc_"
      "method\":\"/grpc.testing.EchoTestService/Echo\"}");
  expected.push_back(
      "{\"authorized\":true,\"matched_rule\":\"policy\","
      "\"policy_name\":\"rbac1\",\"principal\":\"\",\"rpc_"
      "method\":\"/grpc.testing.EchoTestService/Echo\"}");
}
EXPECT_THAT(audit_logs_, ElementsAreArray(expected));

In other words, the advantage of ElementsAreArray() over ElementsAre() is that the former allows you to construct the list separately, not specifying it as a literal in the expectation itself. If you're going to specify it linearly in the expectation itself, then you might as well stick with ElementsAre(), because ElementsAreArray() doesn't actually provide any additional value (in fact, it's actually slightly more cumbersome).

Having said that, though, it occurs to me that in this case, it's probably easier to just say this:

constexpr absl::string_view kAllowedLog =
    "{\"authorized\":true,\"matched_rule\":\"policy\","
    "\"policy_name\":\"rbac1\",\"principal\":\"\",\"rpc_"
    "method\":\"/grpc.testing.EchoTestService/Echo\"}";
constexpr absl::string_view kDeniedLog =
    "{\"authorized\":false,\"matched_rule\":\"policy\","
    "\"policy_name\":\"rbac1\",\"principal\":\"\",\"rpc_"
    "method\":\"/grpc.testing.EchoTestService/Echo\"}";
if (GetParam().rbac_action() == RBAC_Action_DENY) {
  EXPECT_THAT(audit_logs_, ElementsAre(kAllowedLog, kDeniedLog));
} else {
  EXPECT_THAT(audit_logs_, ElementsAre(kAllowedLog, kAllowedLog, kAllowedLog));
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I didn't realize and indeed was a bit confused about what advantage ElementsAreArray could have.

So I took your first suggestion because the policy name (the filter name here) is not the same for the first and third allowed log. Three rbacs have different names.

@rockspore rockspore merged commit d1c0dc5 into grpc:master May 26, 2023
63 of 65 checks passed
@rockspore rockspore deleted the xds-audit-logging-e2e branch May 26, 2023 19:43
@copybara-service copybara-service bot added the imported Specifies if the PR has been imported to the internal repository label May 26, 2023
@yijiem yijiem added release notes: yes Indicates if PR needs to be in release notes and removed release notes: no Indicates if PR should not be in release notes labels May 31, 2023
eugeneo pushed a commit to eugeneo/grpc that referenced this pull request Jun 1, 2023
Added tests involve:
1. Checking the # of logger invocations with multiple RBACs in the
chain.
2. Verifying content in audit context with action and audit condition
permutations.
3. Confirm custom logger and built-in logger configurations are working.
4. Confirm the feature is protected by the environment variable.

---------

Co-authored-by: rockspore <rockspore@users.noreply.github.com>
@erm-g erm-g removed the release notes: yes Indicates if PR needs to be in release notes label Jun 12, 2023
@yijiem yijiem added the release notes: no Indicates if PR should not be in release notes label Jun 12, 2023
mario-vimal pushed a commit to mario-vimal/grpc that referenced this pull request Jun 15, 2023
Added tests involve:
1. Checking the # of logger invocations with multiple RBACs in the
chain.
2. Verifying content in audit context with action and audit condition
permutations.
3. Confirm custom logger and built-in logger configurations are working.
4. Confirm the feature is protected by the environment variable.

---------

Co-authored-by: rockspore <rockspore@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bloat/none imported Specifies if the PR has been imported to the internal repository lang/c++ per-call-memory/neutral per-channel-memory/neutral release notes: no Indicates if PR should not be in release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants