mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
361 lines
11 KiB
361 lines
11 KiB
3 years ago
|
// Copyright 2021 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 <gmock/gmock.h>
|
||
|
#include <gtest/gtest.h>
|
||
|
|
||
|
#include <grpcpp/channel.h>
|
||
|
#include <grpcpp/client_context.h>
|
||
|
#include <grpcpp/create_channel.h>
|
||
|
#include <grpcpp/security/authorization_policy_provider.h>
|
||
|
#include <grpcpp/server.h>
|
||
|
#include <grpcpp/server_builder.h>
|
||
|
|
||
|
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
|
||
|
#include "src/cpp/client/secure_credentials.h"
|
||
|
#include "src/cpp/server/secure_server_credentials.h"
|
||
|
#include "src/proto/grpc/testing/echo.grpc.pb.h"
|
||
|
#include "test/core/util/port.h"
|
||
|
#include "test/core/util/test_config.h"
|
||
|
#include "test/cpp/end2end/test_service_impl.h"
|
||
|
|
||
|
namespace grpc {
|
||
|
namespace testing {
|
||
|
namespace {
|
||
|
|
||
|
constexpr char kMessage[] = "Hello";
|
||
|
|
||
|
class SdkAuthzEnd2EndTest : public ::testing::Test {
|
||
|
protected:
|
||
|
SdkAuthzEnd2EndTest()
|
||
|
: server_address_(
|
||
|
absl::StrCat("localhost:", grpc_pick_unused_port_or_die())),
|
||
|
server_creds_(
|
||
|
std::shared_ptr<ServerCredentials>(new SecureServerCredentials(
|
||
|
grpc_fake_transport_security_server_credentials_create()))),
|
||
|
channel_creds_(
|
||
|
std::shared_ptr<ChannelCredentials>(new SecureChannelCredentials(
|
||
|
grpc_fake_transport_security_credentials_create()))) {}
|
||
|
|
||
|
~SdkAuthzEnd2EndTest() override { server_->Shutdown(); }
|
||
|
|
||
|
// Replaces existing credentials with insecure credentials.
|
||
|
void UseInsecureCredentials() {
|
||
|
server_creds_ = InsecureServerCredentials();
|
||
|
channel_creds_ = InsecureChannelCredentials();
|
||
|
}
|
||
|
|
||
|
// Creates server with sdk authorization enabled when provider is not null.
|
||
|
void InitServer(
|
||
|
std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
|
||
|
provider) {
|
||
|
ServerBuilder builder;
|
||
|
builder.AddListeningPort(server_address_, std::move(server_creds_));
|
||
|
builder.experimental().SetAuthorizationPolicyProvider(std::move(provider));
|
||
|
builder.RegisterService(&service_);
|
||
|
server_ = builder.BuildAndStart();
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
|
||
|
CreateStaticAuthzPolicyProvider(const std::string& policy) {
|
||
|
grpc::Status status;
|
||
|
auto provider = experimental::StaticDataAuthorizationPolicyProvider::Create(
|
||
|
policy, &status);
|
||
|
EXPECT_TRUE(status.ok());
|
||
|
return provider;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Channel> BuildChannel() {
|
||
|
ChannelArguments args;
|
||
|
return ::grpc::CreateCustomChannel(server_address_, channel_creds_, args);
|
||
|
}
|
||
|
|
||
|
grpc::Status SendRpc(const std::shared_ptr<Channel>& channel,
|
||
|
ClientContext* context,
|
||
|
grpc::testing::EchoResponse* response = nullptr) {
|
||
|
auto stub = grpc::testing::EchoTestService::NewStub(channel);
|
||
|
grpc::testing::EchoRequest request;
|
||
|
request.set_message(kMessage);
|
||
|
return stub->Echo(context, request, response);
|
||
|
}
|
||
|
|
||
|
std::string server_address_;
|
||
|
TestServiceImpl service_;
|
||
|
std::unique_ptr<Server> server_;
|
||
|
std::shared_ptr<ServerCredentials> server_creds_;
|
||
|
std::shared_ptr<ChannelCredentials> channel_creds_;
|
||
|
};
|
||
|
|
||
|
TEST_F(SdkAuthzEnd2EndTest,
|
||
|
StaticInitAllowsRpcRequestNoMatchInDenyMatchInAllow) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_echo\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/Echo\""
|
||
|
" ],"
|
||
|
" \"headers\": ["
|
||
|
" {"
|
||
|
" \"key\": \"key-foo\","
|
||
|
" \"values\": [\"foo1\", \"foo2\"]"
|
||
|
" },"
|
||
|
" {"
|
||
|
" \"key\": \"key-bar\","
|
||
|
" \"values\": [\"bar1\"]"
|
||
|
" }"
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ],"
|
||
|
" \"deny_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"deny_clientstreamingecho\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/ClientStreamingEcho\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
context.AddMetadata("key-foo", "foo2");
|
||
|
context.AddMetadata("key-bar", "bar1");
|
||
|
context.AddMetadata("key-baz", "baz1");
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_TRUE(status.ok());
|
||
|
EXPECT_EQ(resp.message(), kMessage);
|
||
|
}
|
||
|
|
||
|
TEST_F(SdkAuthzEnd2EndTest, StaticInitDeniesRpcRequestNoMatchInAllowAndDeny) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_foo\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/foo\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ],"
|
||
|
" \"deny_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"deny_bar\","
|
||
|
" \"source\": {"
|
||
|
" \"principals\": ["
|
||
|
" \"bar\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
|
||
|
EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
|
||
|
EXPECT_TRUE(resp.message().empty());
|
||
|
}
|
||
|
|
||
|
TEST_F(SdkAuthzEnd2EndTest, StaticInitDeniesRpcRequestMatchInDenyMatchInAllow) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_all\""
|
||
|
" }"
|
||
|
" ],"
|
||
|
" \"deny_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"deny_echo\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/Echo\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
|
||
|
EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
|
||
|
EXPECT_TRUE(resp.message().empty());
|
||
|
}
|
||
|
|
||
|
TEST_F(SdkAuthzEnd2EndTest,
|
||
|
StaticInitDeniesRpcRequestMatchInDenyNoMatchInAllow) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_clientstreamingecho\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/ClientStreamingEcho\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ],"
|
||
|
" \"deny_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"deny_echo\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/Echo\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
|
||
|
EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
|
||
|
EXPECT_TRUE(resp.message().empty());
|
||
|
}
|
||
|
|
||
|
TEST_F(SdkAuthzEnd2EndTest, StaticInitAllowsRpcRequestEmptyDenyMatchInAllow) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_echo\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/Echo\""
|
||
|
" ],"
|
||
|
" \"headers\": ["
|
||
|
" {"
|
||
|
" \"key\": \"key-foo\","
|
||
|
" \"values\": [\"foo1\", \"foo2\"]"
|
||
|
" },"
|
||
|
" {"
|
||
|
" \"key\": \"key-bar\","
|
||
|
" \"values\": [\"bar1\"]"
|
||
|
" }"
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
context.AddMetadata("key-foo", "foo2");
|
||
|
context.AddMetadata("key-bar", "bar1");
|
||
|
context.AddMetadata("key-baz", "baz1");
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_TRUE(status.ok());
|
||
|
EXPECT_EQ(resp.message(), kMessage);
|
||
|
}
|
||
|
|
||
|
TEST_F(SdkAuthzEnd2EndTest, StaticInitDeniesRpcRequestEmptyDenyNoMatchInAllow) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_echo\","
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/Echo\""
|
||
|
" ],"
|
||
|
" \"headers\": ["
|
||
|
" {"
|
||
|
" \"key\": \"key-foo\","
|
||
|
" \"values\": [\"foo1\"]"
|
||
|
" }"
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
context.AddMetadata("key-bar", "bar1");
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
|
||
|
EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
|
||
|
EXPECT_TRUE(resp.message().empty());
|
||
|
}
|
||
|
|
||
|
TEST_F(
|
||
|
SdkAuthzEnd2EndTest,
|
||
|
StaticInitDeniesRpcRequestWithPrincipalsFieldOnUnauthenticatedConnection) {
|
||
|
std::string policy =
|
||
|
"{"
|
||
|
" \"name\": \"authz\","
|
||
|
" \"allow_rules\": ["
|
||
|
" {"
|
||
|
" \"name\": \"allow_echo\","
|
||
|
" \"source\": {"
|
||
|
" \"principals\": ["
|
||
|
" \"foo\""
|
||
|
" ]"
|
||
|
" },"
|
||
|
" \"request\": {"
|
||
|
" \"paths\": ["
|
||
|
" \"*/Echo\""
|
||
|
" ]"
|
||
|
" }"
|
||
|
" }"
|
||
|
" ]"
|
||
|
"}";
|
||
|
UseInsecureCredentials();
|
||
|
InitServer(CreateStaticAuthzPolicyProvider(policy));
|
||
|
auto channel = BuildChannel();
|
||
|
ClientContext context;
|
||
|
grpc::testing::EchoResponse resp;
|
||
|
grpc::Status status = SendRpc(channel, &context, &resp);
|
||
|
EXPECT_EQ(status.error_code(), grpc::StatusCode::PERMISSION_DENIED);
|
||
|
EXPECT_EQ(status.error_message(), "Unauthorized RPC request rejected.");
|
||
|
EXPECT_TRUE(resp.message().empty());
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
} // namespace testing
|
||
|
} // namespace grpc
|
||
|
|
||
|
int main(int argc, char** argv) {
|
||
|
::testing::InitGoogleTest(&argc, argv);
|
||
|
grpc::testing::TestEnvironment env(argc, argv);
|
||
|
const auto result = RUN_ALL_TESTS();
|
||
|
return result;
|
||
|
}
|