diff --git a/Makefile b/Makefile index f186e5b086ea5ea617038c66baf14b9f0d83b2bc..6917ef51bef54efd3030c2a825c14d83bfe6e3ed 100644 --- a/Makefile +++ b/Makefile @@ -308,7 +308,7 @@ E = @echo Q = @ endif -VERSION = 0.8.0.0 +VERSION = 0.9.0.0 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) @@ -3045,6 +3045,7 @@ LIBGRPC++_TEST_UTIL_SRC = \ $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc \ test/cpp/util/cli_call.cc \ test/cpp/util/create_test_channel.cc \ + test/cpp/util/fake_credentials.cc \ LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_SRC)))) @@ -3090,6 +3091,7 @@ endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/cli_call.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/messages.grpc.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo.grpc.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/create_test_channel.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/messages.grpc.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo.grpc.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc +$(OBJDIR)/$(CONFIG)/test/cpp/util/fake_credentials.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/messages.grpc.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo.grpc.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc LIBGRPC++_UNSECURE_SRC = \ diff --git a/build.json b/build.json index 882c3cb6abc4a86b1a26688cf96138532e2480df..d969121559a0a62bc5b1b3081776392b8a051cfb 100644 --- a/build.json +++ b/build.json @@ -6,7 +6,7 @@ "#": "The public version number of the library.", "version": { "major": 0, - "minor": 8, + "minor": 9, "micro": 0, "build": 0 } @@ -543,7 +543,8 @@ "test/cpp/util/echo.proto", "test/cpp/util/echo_duplicate.proto", "test/cpp/util/cli_call.cc", - "test/cpp/util/create_test_channel.cc" + "test/cpp/util/create_test_channel.cc", + "test/cpp/util/fake_credentials.cc" ] }, { diff --git a/examples/pubsub/main.cc b/examples/pubsub/main.cc index 68620e64c5c280f63632fa68c6f5bdd56b439a49..b1898f18d9a102504ddf4e4a289b7f57bc264cfe 100644 --- a/examples/pubsub/main.cc +++ b/examples/pubsub/main.cc @@ -71,7 +71,7 @@ int main(int argc, char** argv) { ss << FLAGS_server_host << ":" << FLAGS_server_port; - std::unique_ptr<grpc::Credentials> creds = grpc::GoogleDefaultCredentials(); + std::shared_ptr<grpc::Credentials> creds = grpc::GoogleDefaultCredentials(); std::shared_ptr<grpc::ChannelInterface> channel = grpc::CreateChannel(ss.str(), creds, grpc::ChannelArguments()); diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h index a58e9872e6097ad1886afc0adeda28e095d4a8f9..6d9015f278cc852ab4a0d37943e3ff87b6384844 100644 --- a/include/grpc++/client_context.h +++ b/include/grpc++/client_context.h @@ -51,6 +51,7 @@ namespace grpc { class CallOpBuffer; class ChannelInterface; class CompletionQueue; +class Credentials; class RpcMethod; class Status; template <class R> @@ -102,6 +103,11 @@ class ClientContext { void set_authority(const grpc::string& authority) { authority_ = authority; } + // Set credentials for the rpc. + void set_credentials(const std::shared_ptr<Credentials>& creds) { + creds_ = creds; + } + void TryCancel(); private: @@ -127,11 +133,8 @@ class ClientContext { friend class ::grpc::ClientAsyncResponseReader; grpc_call* call() { return call_; } - void set_call(grpc_call* call, const std::shared_ptr<ChannelInterface>& channel) { - GPR_ASSERT(call_ == nullptr); - call_ = call; - channel_ = channel; - } + void set_call(grpc_call* call, + const std::shared_ptr<ChannelInterface>& channel); grpc_completion_queue* cq() { return cq_; } void set_cq(grpc_completion_queue* cq) { cq_ = cq; } @@ -144,6 +147,7 @@ class ClientContext { grpc_completion_queue* cq_; gpr_timespec deadline_; grpc::string authority_; + std::shared_ptr<Credentials> creds_; std::multimap<grpc::string, grpc::string> send_initial_metadata_; std::multimap<grpc::string, grpc::string> recv_initial_metadata_; std::multimap<grpc::string, grpc::string> trailing_metadata_; diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h index da375b97db457f1edf225e7934da734efb96b1ff..424a93a64c5939be47cdfb73437342fdbdadfcf4 100644 --- a/include/grpc++/create_channel.h +++ b/include/grpc++/create_channel.h @@ -45,7 +45,7 @@ class ChannelInterface; // If creds does not hold an object or is invalid, a lame channel is returned. std::shared_ptr<ChannelInterface> CreateChannel( - const grpc::string& target, const std::unique_ptr<Credentials>& creds, + const grpc::string& target, const std::shared_ptr<Credentials>& creds, const ChannelArguments& args); } // namespace grpc diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h index 61c40946910301cd35f205c58d17addfd69d1775..7a40cd199d8499080bbee7a13bd500d3761f3893 100644 --- a/include/grpc++/credentials.h +++ b/include/grpc++/credentials.h @@ -47,17 +47,18 @@ class SecureCredentials; class Credentials : public GrpcLibrary { public: ~Credentials() GRPC_OVERRIDE; + virtual bool ApplyToCall(grpc_call* call) = 0; protected: - friend std::unique_ptr<Credentials> CompositeCredentials( - const std::unique_ptr<Credentials>& creds1, - const std::unique_ptr<Credentials>& creds2); + friend std::shared_ptr<Credentials> CompositeCredentials( + const std::shared_ptr<Credentials>& creds1, + const std::shared_ptr<Credentials>& creds2); virtual SecureCredentials* AsSecureCredentials() = 0; private: friend std::shared_ptr<ChannelInterface> CreateChannel( - const grpc::string& target, const std::unique_ptr<Credentials>& creds, + const grpc::string& target, const std::shared_ptr<Credentials>& creds, const ChannelArguments& args); virtual std::shared_ptr<ChannelInterface> CreateChannel( @@ -80,20 +81,20 @@ struct SslCredentialsOptions { }; // Factories for building different types of Credentials -// The functions may return empty unique_ptr when credentials cannot be created. +// The functions may return empty shared_ptr when credentials cannot be created. // If a Credentials pointer is returned, it can still be invalid when used to // create a channel. A lame channel will be created then and all rpcs will // fail on it. // Builds credentials with reasonable defaults. -std::unique_ptr<Credentials> GoogleDefaultCredentials(); +std::shared_ptr<Credentials> GoogleDefaultCredentials(); // Builds SSL Credentials given SSL specific options -std::unique_ptr<Credentials> SslCredentials( +std::shared_ptr<Credentials> SslCredentials( const SslCredentialsOptions& options); // Builds credentials for use when running in GCE -std::unique_ptr<Credentials> ComputeEngineCredentials(); +std::shared_ptr<Credentials> ComputeEngineCredentials(); // Builds service account credentials. // json_key is the JSON key string containing the client's private key. @@ -101,7 +102,7 @@ std::unique_ptr<Credentials> ComputeEngineCredentials(); // token_lifetime_seconds is the lifetime in seconds of each token acquired // through this service account credentials. It should be positive and should // not exceed grpc_max_auth_token_lifetime or will be cropped to this value. -std::unique_ptr<Credentials> ServiceAccountCredentials( +std::shared_ptr<Credentials> ServiceAccountCredentials( const grpc::string& json_key, const grpc::string& scope, long token_lifetime_seconds); @@ -110,27 +111,27 @@ std::unique_ptr<Credentials> ServiceAccountCredentials( // token_lifetime_seconds is the lifetime in seconds of each Json Web Token // (JWT) created with this credentials. It should not exceed // grpc_max_auth_token_lifetime or will be cropped to this value. -std::unique_ptr<Credentials> JWTCredentials( - const grpc::string& json_key, long token_lifetime_seconds); +std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key, + long token_lifetime_seconds); // Builds refresh token credentials. // json_refresh_token is the JSON string containing the refresh token along // with a client_id and client_secret. -std::unique_ptr<Credentials> RefreshTokenCredentials( +std::shared_ptr<Credentials> RefreshTokenCredentials( const grpc::string& json_refresh_token); // Builds IAM credentials. -std::unique_ptr<Credentials> IAMCredentials( +std::shared_ptr<Credentials> IAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector); // Combines two credentials objects into a composite credentials -std::unique_ptr<Credentials> CompositeCredentials( - const std::unique_ptr<Credentials>& creds1, - const std::unique_ptr<Credentials>& creds2); +std::shared_ptr<Credentials> CompositeCredentials( + const std::shared_ptr<Credentials>& creds1, + const std::shared_ptr<Credentials>& creds2); // Credentials for an unencrypted, unauthenticated channel -std::unique_ptr<Credentials> InsecureCredentials(); +std::shared_ptr<Credentials> InsecureCredentials(); } // namespace grpc diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index f38a694734ab93b0b0fd33637f2b1ca8939e9d4b..72cdd49d195f99616f865c40b1b94ff1c819ab35 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -34,6 +34,7 @@ #include <grpc++/client_context.h> #include <grpc/grpc.h> +#include <grpc++/credentials.h> #include <grpc++/time.h> namespace grpc { @@ -63,6 +64,17 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, send_initial_metadata_.insert(std::make_pair(meta_key, meta_value)); } +void ClientContext::set_call(grpc_call* call, + const std::shared_ptr<ChannelInterface>& channel) { + GPR_ASSERT(call_ == nullptr); + call_ = call; + channel_ = channel; + if (creds_ && !creds_->ApplyToCall(call_)) { + grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, + "Failed to set credentials to rpc."); + } +} + void ClientContext::TryCancel() { if (call_) { grpc_call_cancel(call_); diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 301430572a24b6e896e6d729784fe745ebc135b3..510af2bb00a4b95bb0bdca402968e9f17c6be368 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -41,7 +41,7 @@ namespace grpc { class ChannelArguments; std::shared_ptr<ChannelInterface> CreateChannel( - const grpc::string& target, const std::unique_ptr<Credentials>& creds, + const grpc::string& target, const std::shared_ptr<Credentials>& creds, const ChannelArguments& args) { return creds ? creds->CreateChannel(target, args) : std::shared_ptr<ChannelInterface>( diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc index 8945b038dec586dacbb6a1086c82b4be60d31374..5ad87845675f03ba65503d5b57b2a06f59155b4f 100644 --- a/src/cpp/client/insecure_credentials.cc +++ b/src/cpp/client/insecure_credentials.cc @@ -52,12 +52,15 @@ class InsecureCredentialsImpl GRPC_FINAL : public Credentials { target, grpc_channel_create(target.c_str(), &channel_args))); } + // InsecureCredentials should not be applied to a call. + bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE { return false; } + SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return nullptr; } }; } // namespace -std::unique_ptr<Credentials> InsecureCredentials() { - return std::unique_ptr<Credentials>(new InsecureCredentialsImpl()); +std::shared_ptr<Credentials> InsecureCredentials() { + return std::shared_ptr<Credentials>(new InsecureCredentialsImpl()); } } // namespace grpc diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index 48bf7430b27bf924a1f689e86b75dfad975a1268..b5134b31403cc523b260e6949312951e344ea7b7 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -49,20 +49,24 @@ std::shared_ptr<grpc::ChannelInterface> SecureCredentials::CreateChannel( grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args))); } +bool SecureCredentials::ApplyToCall(grpc_call* call) { + return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK; +} + namespace { -std::unique_ptr<Credentials> WrapCredentials(grpc_credentials* creds) { +std::shared_ptr<Credentials> WrapCredentials(grpc_credentials* creds) { return creds == nullptr ? nullptr - : std::unique_ptr<Credentials>(new SecureCredentials(creds)); + : std::shared_ptr<Credentials>(new SecureCredentials(creds)); } } // namespace -std::unique_ptr<Credentials> GoogleDefaultCredentials() { +std::shared_ptr<Credentials> GoogleDefaultCredentials() { return WrapCredentials(grpc_google_default_credentials_create()); } // Builds SSL Credentials given SSL specific options -std::unique_ptr<Credentials> SslCredentials( +std::shared_ptr<Credentials> SslCredentials( const SslCredentialsOptions& options) { grpc_ssl_pem_key_cert_pair pem_key_cert_pair = { options.pem_private_key.c_str(), options.pem_cert_chain.c_str()}; @@ -74,12 +78,12 @@ std::unique_ptr<Credentials> SslCredentials( } // Builds credentials for use when running in GCE -std::unique_ptr<Credentials> ComputeEngineCredentials() { +std::shared_ptr<Credentials> ComputeEngineCredentials() { return WrapCredentials(grpc_compute_engine_credentials_create()); } // Builds service account credentials. -std::unique_ptr<Credentials> ServiceAccountCredentials( +std::shared_ptr<Credentials> ServiceAccountCredentials( const grpc::string& json_key, const grpc::string& scope, long token_lifetime_seconds) { if (token_lifetime_seconds <= 0) { @@ -94,8 +98,8 @@ std::unique_ptr<Credentials> ServiceAccountCredentials( } // Builds JWT credentials. -std::unique_ptr<Credentials> JWTCredentials( - const grpc::string& json_key, long token_lifetime_seconds) { +std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key, + long token_lifetime_seconds) { if (token_lifetime_seconds <= 0) { gpr_log(GPR_ERROR, "Trying to create JWTCredentials with non-positive lifetime"); @@ -107,14 +111,14 @@ std::unique_ptr<Credentials> JWTCredentials( } // Builds refresh token credentials. -std::unique_ptr<Credentials> RefreshTokenCredentials( +std::shared_ptr<Credentials> RefreshTokenCredentials( const grpc::string& json_refresh_token) { return WrapCredentials( grpc_refresh_token_credentials_create(json_refresh_token.c_str())); } // Builds IAM credentials. -std::unique_ptr<Credentials> IAMCredentials( +std::shared_ptr<Credentials> IAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector) { return WrapCredentials(grpc_iam_credentials_create( @@ -122,10 +126,10 @@ std::unique_ptr<Credentials> IAMCredentials( } // Combines two credentials objects into a composite credentials. -std::unique_ptr<Credentials> CompositeCredentials( - const std::unique_ptr<Credentials>& creds1, - const std::unique_ptr<Credentials>& creds2) { - // Note that we are not saving unique_ptrs to the two credentials +std::shared_ptr<Credentials> CompositeCredentials( + const std::shared_ptr<Credentials>& creds1, + const std::shared_ptr<Credentials>& creds2) { + // Note that we are not saving shared_ptrs to the two credentials // passed in here. This is OK because the underlying C objects (i.e., // creds1 and creds2) into grpc_composite_credentials_create will see their // refcounts incremented. diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h index 77d575813eae2968b6139862a385d0aaf1d0b71d..ddf69911b5fa39744f63631e33b14fb8ef5e9bd3 100644 --- a/src/cpp/client/secure_credentials.h +++ b/src/cpp/client/secure_credentials.h @@ -46,6 +46,7 @@ class SecureCredentials GRPC_FINAL : public Credentials { explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {} ~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); } grpc_credentials* GetRawCreds() { return c_creds_; } + bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE; std::shared_ptr<grpc::ChannelInterface> CreateChannel( const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE; diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index 6840418989cb1bad0bf524bbfba8b895e7a8eeab..ee94f455a436ede1b8c74c2dbc9e5e8f41d73440 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -46,8 +46,7 @@ class CredentialsTest : public ::testing::Test { }; TEST_F(CredentialsTest, InvalidServiceAccountCreds) { - std::unique_ptr<Credentials> bad1 = - ServiceAccountCredentials("", "", 1); + std::shared_ptr<Credentials> bad1 = ServiceAccountCredentials("", "", 1); EXPECT_EQ(nullptr, bad1.get()); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index f35b16fe5556921545e7abf36a0511a4ae70d98e..76271c3e1dd934879efb8270db3c172f7812692c 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -33,11 +33,13 @@ #include <thread> +#include "src/core/security/credentials.h" +#include "src/cpp/server/thread_pool.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" #include "test/cpp/util/echo_duplicate.grpc.pb.h" #include "test/cpp/util/echo.grpc.pb.h" -#include "src/cpp/server/thread_pool.h" +#include "test/cpp/util/fake_credentials.h" #include <grpc++/channel_arguments.h> #include <grpc++/channel_interface.h> #include <grpc++/client_context.h> @@ -106,6 +108,16 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service { } else { EXPECT_FALSE(context->IsCancelled()); } + + if (request->has_param() && request->param().echo_metadata()) { + const std::multimap<grpc::string, grpc::string>& client_metadata = + context->client_metadata(); + for (std::multimap<grpc::string, grpc::string>::const_iterator iter = + client_metadata.begin(); + iter != client_metadata.end(); ++iter) { + context->AddTrailingMetadata((*iter).first, (*iter).second); + } + } return Status::OK; } @@ -180,7 +192,7 @@ class End2endTest : public ::testing::Test { // Setup server ServerBuilder builder; builder.AddListeningPort(server_address_.str(), - InsecureServerCredentials()); + FakeTransportSecurityServerCredentials()); builder.RegisterService(&service_); builder.SetMaxMessageSize( kMaxMessageSize_); // For testing max message size. @@ -192,8 +204,9 @@ class End2endTest : public ::testing::Test { void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } void ResetStub() { - std::shared_ptr<ChannelInterface> channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = + CreateChannel(server_address_.str(), FakeTransportSecurityCredentials(), + ChannelArguments()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } @@ -404,8 +417,9 @@ TEST_F(End2endTest, BidiStream) { // Talk to the two services with the same name but different package names. // The two stubs are created on the same channel. TEST_F(End2endTest, DiffPackageServices) { - std::shared_ptr<ChannelInterface> channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = + CreateChannel(server_address_.str(), FakeTransportSecurityCredentials(), + ChannelArguments()); EchoRequest request; EchoResponse response; @@ -429,7 +443,7 @@ TEST_F(End2endTest, DiffPackageServices) { // rpc and stream should fail on bad credentials. TEST_F(End2endTest, BadCredentials) { - std::unique_ptr<Credentials> bad_creds = ServiceAccountCredentials("", "", 1); + std::shared_ptr<Credentials> bad_creds = ServiceAccountCredentials("", "", 1); EXPECT_EQ(nullptr, bad_creds.get()); std::shared_ptr<ChannelInterface> channel = CreateChannel(server_address_.str(), bad_creds, ChannelArguments()); @@ -438,7 +452,7 @@ TEST_F(End2endTest, BadCredentials) { EchoRequest request; EchoResponse response; ClientContext context; - grpc::string msg("hello"); + request.set_message("Hello"); Status s = stub->Echo(&context, request, &response); EXPECT_EQ("", response.message()); @@ -588,6 +602,88 @@ TEST_F(End2endTest, RpcMaxMessageSize) { EXPECT_FALSE(s.IsOk()); } +bool MetadataContains(const std::multimap<grpc::string, grpc::string>& metadata, + const grpc::string& key, const grpc::string& value) { + int count = 0; + + for (std::multimap<grpc::string, grpc::string>::const_iterator iter = + metadata.begin(); + iter != metadata.end(); ++iter) { + if ((*iter).first == key && (*iter).second == value) { + count++; + } + } + return count == 1; +} + +TEST_F(End2endTest, SetPerCallCredentials) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + std::shared_ptr<Credentials> creds = + IAMCredentials("fake_token", "fake_selector"); + context.set_credentials(creds); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.IsOk()); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + "fake_token")); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + "fake_selector")); +} + +TEST_F(End2endTest, InsecurePerCallCredentials) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + std::shared_ptr<Credentials> creds = InsecureCredentials(); + context.set_credentials(creds); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(StatusCode::CANCELLED, s.code()); + EXPECT_EQ("Failed to set credentials to rpc.", s.details()); +} + +TEST_F(End2endTest, OverridePerCallCredentials) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + std::shared_ptr<Credentials> creds1 = + IAMCredentials("fake_token1", "fake_selector1"); + context.set_credentials(creds1); + std::shared_ptr<Credentials> creds2 = + IAMCredentials("fake_token2", "fake_selector2"); + context.set_credentials(creds2); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + "fake_token2")); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + "fake_selector2")); + EXPECT_FALSE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + "fake_token1")); + EXPECT_FALSE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + "fake_selector1")); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.IsOk()); +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc index a1dea383e6a3b683fbb8253a63bc69ef06637a48..09fd1c8913f38ccc24ef50490891dc61cc4823df 100644 --- a/test/cpp/interop/client_helper.cc +++ b/test/cpp/interop/client_helper.cc @@ -82,7 +82,7 @@ std::shared_ptr<ChannelInterface> CreateChannelForTestCase( FLAGS_server_port); if (test_case == "service_account_creds") { - std::unique_ptr<Credentials> creds; + std::shared_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); grpc::string json_key = GetServiceAccountJsonKey(); std::chrono::seconds token_lifetime = std::chrono::hours(1); @@ -91,13 +91,13 @@ std::shared_ptr<ChannelInterface> CreateChannelForTestCase( return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else if (test_case == "compute_engine_creds") { - std::unique_ptr<Credentials> creds; + std::shared_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); creds = ComputeEngineCredentials(); return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else if (test_case == "jwt_token_creds") { - std::unique_ptr<Credentials> creds; + std::shared_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); grpc::string json_key = GetServiceAccountJsonKey(); std::chrono::seconds token_lifetime = std::chrono::hours(1); diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index f040acc4b1fcba91105f75d3e23816aad69acd91..dc48fa2d87f995a438b79588b8f040252e6e23ab 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -58,13 +58,13 @@ namespace grpc { std::shared_ptr<ChannelInterface> CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, bool enable_ssl, bool use_prod_roots, - const std::unique_ptr<Credentials>& creds) { + const std::shared_ptr<Credentials>& creds) { ChannelArguments channel_args; if (enable_ssl) { const char* roots_certs = use_prod_roots ? "" : test_root_cert; SslCredentialsOptions ssl_opts = {roots_certs, "", ""}; - std::unique_ptr<Credentials> channel_creds = SslCredentials(ssl_opts); + std::shared_ptr<Credentials> channel_creds = SslCredentials(ssl_opts); if (!server.empty() && !override_hostname.empty()) { channel_args.SetSslTargetNameOverride(override_hostname); @@ -84,7 +84,7 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, bool enable_ssl, bool use_prod_roots) { return CreateTestChannel(server, override_hostname, enable_ssl, - use_prod_roots, std::unique_ptr<Credentials>()); + use_prod_roots, std::shared_ptr<Credentials>()); } // Shortcut for end2end and interop tests. diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index 5c298ce8504604bf7989791e28e856cd2a938175..5f2609ddd81e5de0b2c7c830ec920721ffaf5bdc 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -52,7 +52,7 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( std::shared_ptr<ChannelInterface> CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, bool enable_ssl, bool use_prod_roots, - const std::unique_ptr<Credentials>& creds); + const std::shared_ptr<Credentials>& creds); } // namespace grpc diff --git a/test/cpp/util/fake_credentials.cc b/test/cpp/util/fake_credentials.cc new file mode 100644 index 0000000000000000000000000000000000000000..f5b83b8159f9ce3765cd90cf161eb43514f49002 --- /dev/null +++ b/test/cpp/util/fake_credentials.cc @@ -0,0 +1,58 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/grpc_security.h> +#include <grpc++/channel_arguments.h> +#include <grpc++/credentials.h> +#include <grpc++/server_credentials.h> +#include "src/cpp/client/channel.h" +#include "src/cpp/client/secure_credentials.h" +#include "src/cpp/server/secure_server_credentials.h" + +namespace grpc { +namespace testing { + +std::shared_ptr<Credentials> FakeTransportSecurityCredentials() { + grpc_credentials* c_creds = grpc_fake_transport_security_credentials_create(); + return std::shared_ptr<Credentials>(new SecureCredentials(c_creds)); +} + +std::shared_ptr<ServerCredentials> FakeTransportSecurityServerCredentials() { + grpc_server_credentials* c_creds = + grpc_fake_transport_security_server_credentials_create(); + return std::shared_ptr<ServerCredentials>( + new SecureServerCredentials(c_creds)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/util/fake_credentials.h b/test/cpp/util/fake_credentials.h new file mode 100644 index 0000000000000000000000000000000000000000..e1ba7bb9e4ae47fe869e4ad6897beee963c02b17 --- /dev/null +++ b/test/cpp/util/fake_credentials.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H +#define GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H + +#include <memory> + +namespace grpc { +class Credentials; +class ServerCredentials; + +namespace testing { + +std::shared_ptr<Credentials> FakeTransportSecurityCredentials(); +std::shared_ptr<ServerCredentials> FakeTransportSecurityServerCredentials(); + +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc index d71a7a0b778dc1400cc2706d7dcf94b1d595530a..ad3c0af8775980577e42db833bbd356b2f23f358 100644 --- a/test/cpp/util/grpc_cli.cc +++ b/test/cpp/util/grpc_cli.cc @@ -104,7 +104,7 @@ int main(int argc, char** argv) { std::stringstream input_stream; input_stream << input_file.rdbuf(); - std::unique_ptr<grpc::Credentials> creds; + std::shared_ptr<grpc::Credentials> creds; if (!FLAGS_enable_ssl) { creds = grpc::InsecureCredentials(); } else { diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto index a79bce1f306267a50c65c1c745f36c1982bf8c0c..062f66c0918b6320b23bdc43c77019eb51134129 100644 --- a/test/cpp/util/messages.proto +++ b/test/cpp/util/messages.proto @@ -36,6 +36,7 @@ message RequestParams { optional bool echo_deadline = 1; optional int32 client_cancel_after_us = 2; optional int32 server_cancel_after_us = 3; + optional bool echo_metadata = 4; } message EchoRequest {