@ -37,6 +37,7 @@
# include <grpc/grpc.h>
# include <grpc/support/thd.h>
# include <grpc/support/time.h>
# include <grpc++/auth_metadata_processor.h>
# include <grpc++/channel.h>
# include <grpc++/client_context.h>
# include <grpc++/create_channel.h>
@ -79,14 +80,23 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
}
}
void CheckServerAuthContext ( const ServerContext * context ) {
void CheckServerAuthContext ( const ServerContext * context ,
const grpc : : string & expected_client_identity ) {
std : : shared_ptr < const AuthContext > auth_ctx = context - > auth_context ( ) ;
std : : vector < grpc : : string_ref > ssl =
auth_ctx - > FindPropertyValues ( " transport_security_type " ) ;
EXPECT_EQ ( 1u , ssl . size ( ) ) ;
EXPECT_EQ ( " ssl " , ToString ( ssl [ 0 ] ) ) ;
EXPECT_TRUE ( auth_ctx - > GetPeerIdentityPropertyName ( ) . empty ( ) ) ;
EXPECT_TRUE ( auth_ctx - > GetPeerIdentity ( ) . empty ( ) ) ;
if ( expected_client_identity . length ( ) = = 0 ) {
EXPECT_TRUE ( auth_ctx - > GetPeerIdentityPropertyName ( ) . empty ( ) ) ;
EXPECT_TRUE ( auth_ctx - > GetPeerIdentity ( ) . empty ( ) ) ;
EXPECT_FALSE ( auth_ctx - > IsPeerAuthenticated ( ) ) ;
} else {
auto identity = auth_ctx - > GetPeerIdentity ( ) ;
EXPECT_TRUE ( auth_ctx - > IsPeerAuthenticated ( ) ) ;
EXPECT_EQ ( 1u , identity . size ( ) ) ;
EXPECT_EQ ( expected_client_identity , identity [ 0 ] ) ;
}
}
bool CheckIsLocalhost ( const grpc : : string & addr ) {
@ -98,6 +108,54 @@ bool CheckIsLocalhost(const grpc::string& addr) {
addr . substr ( 0 , kIpv6 . size ( ) ) = = kIpv6 ;
}
class TestAuthMetadataProcessor : public AuthMetadataProcessor {
public :
static const char kGoodGuy [ ] ;
TestAuthMetadataProcessor ( bool is_blocking ) : is_blocking_ ( is_blocking ) { }
std : : shared_ptr < Credentials > GetCompatibleClientCreds ( ) {
return AccessTokenCredentials ( kGoodGuy ) ;
}
std : : shared_ptr < Credentials > GetIncompatibleClientCreds ( ) {
return AccessTokenCredentials ( " Mr Hyde " ) ;
}
// Interface implementation
bool IsBlocking ( ) const GRPC_OVERRIDE { return is_blocking_ ; }
Status Process ( const InputMetadata & auth_metadata , AuthContext * context ,
OutputMetadata * consumed_auth_metadata ,
OutputMetadata * response_metadata ) GRPC_OVERRIDE {
EXPECT_TRUE ( consumed_auth_metadata ! = nullptr ) ;
EXPECT_TRUE ( context ! = nullptr ) ;
EXPECT_TRUE ( response_metadata ! = nullptr ) ;
auto auth_md = auth_metadata . find ( GRPC_AUTHORIZATION_METADATA_KEY ) ;
EXPECT_NE ( auth_md , auth_metadata . end ( ) ) ;
string_ref auth_md_value = auth_md - > second ;
if ( auth_md_value . ends_with ( " Dr Jekyll " ) ) {
context - > AddProperty ( kIdentityPropName , kGoodGuy ) ;
context - > SetPeerIdentityPropertyName ( kIdentityPropName ) ;
consumed_auth_metadata - > insert (
std : : make_pair ( string ( auth_md - > first . data ( ) , auth_md - > first . length ( ) ) ,
auth_md - > second ) ) ;
return Status : : OK ;
} else {
return Status ( StatusCode : : UNAUTHENTICATED ,
string ( " Invalid principal: " ) +
string ( auth_md_value . data ( ) , auth_md_value . length ( ) ) ) ;
}
}
protected :
static const char kIdentityPropName [ ] ;
bool is_blocking_ ;
} ;
const char TestAuthMetadataProcessor : : kGoodGuy [ ] = " Dr Jekyll " ;
const char TestAuthMetadataProcessor : : kIdentityPropName [ ] = " novel identity " ;
} // namespace
class Proxy : public : : grpc : : cpp : : test : : util : : TestService : : Service {
@ -162,8 +220,10 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
ToString ( iter - > second ) ) ;
}
}
if ( request - > has_param ( ) & & request - > param ( ) . check_auth_context ( ) ) {
CheckServerAuthContext ( context ) ;
if ( request - > has_param ( ) & &
( request - > param ( ) . expected_client_identity ( ) . length ( ) > 0 | |
request - > param ( ) . check_auth_context ( ) ) ) {
CheckServerAuthContext ( context , request - > param ( ) . expected_client_identity ( ) ) ;
}
if ( request - > has_param ( ) & &
request - > param ( ) . response_message_length ( ) > 0 ) {
@ -259,9 +319,18 @@ class TestServiceImplDupPkg
class End2endTest : public : : testing : : TestWithParam < bool > {
protected :
End2endTest ( )
: kMaxMessageSize_ ( 8192 ) , special_service_ ( " special " ) { }
: is_server_started_ ( false ) ,
kMaxMessageSize_ ( 8192 ) ,
special_service_ ( " special " ) { }
void TearDown ( ) GRPC_OVERRIDE {
if ( is_server_started_ ) {
server_ - > Shutdown ( ) ;
if ( proxy_server_ ) proxy_server_ - > Shutdown ( ) ;
}
}
void SetUp ( ) GRPC_OVERRIDE {
void StartServer ( const std : : shared_ptr < AuthMetadataProcessor > & processor ) {
int port = grpc_pick_unused_port_or_die ( ) ;
server_address_ < < " 127.0.0.1: " < < port ;
// Setup server
@ -271,22 +340,23 @@ class End2endTest : public ::testing::TestWithParam<bool> {
SslServerCredentialsOptions ssl_opts ;
ssl_opts . pem_root_certs = " " ;
ssl_opts . pem_key_cert_pairs . push_back ( pkcp ) ;
builder . AddListeningPort ( server_address_ . str ( ) ,
SslServerCredentials ( ssl_opts ) ) ;
auto server_creds = SslServerCredentials ( ssl_opts ) ;
server_creds - > SetAuthMetadataProcessor ( processor ) ;
builder . AddListeningPort ( server_address_ . str ( ) , server_creds ) ;
builder . RegisterService ( & service_ ) ;
builder . RegisterService ( " foo.test.youtube.com " , & special_service_ ) ;
builder . SetMaxMessageSize (
kMaxMessageSize_ ) ; // For testing max message size.
builder . RegisterService ( & dup_pkg_service_ ) ;
server_ = builder . BuildAndStart ( ) ;
}
void TearDown ( ) GRPC_OVERRIDE {
server_ - > Shutdown ( ) ;
if ( proxy_server_ ) proxy_server_ - > Shutdown ( ) ;
is_server_started_ = true ;
}
void ResetChannel ( ) {
if ( ! is_server_started_ ) {
StartServer ( std : : shared_ptr < AuthMetadataProcessor > ( ) ) ;
}
EXPECT_TRUE ( is_server_started_ ) ;
SslCredentialsOptions ssl_opts = { test_root_cert , " " , " " } ;
ChannelArguments args ;
args . SetSslTargetNameOverride ( " foo.test.google.fr " ) ;
@ -314,6 +384,7 @@ class End2endTest : public ::testing::TestWithParam<bool> {
stub_ = std : : move ( grpc : : cpp : : test : : util : : TestService : : NewStub ( channel_ ) ) ;
}
bool is_server_started_ ;
std : : shared_ptr < Channel > channel_ ;
std : : unique_ptr < grpc : : cpp : : test : : util : : TestService : : Stub > stub_ ;
std : : unique_ptr < Server > server_ ;
@ -806,6 +877,82 @@ TEST_F(End2endTest, OverridePerCallCredentials) {
EXPECT_TRUE ( s . ok ( ) ) ;
}
TEST_F ( End2endTest , NonBlockingAuthMetadataProcessorSuccess ) {
auto * processor = new TestAuthMetadataProcessor ( false ) ;
StartServer ( std : : shared_ptr < AuthMetadataProcessor > ( processor ) ) ;
ResetStub ( false ) ;
EchoRequest request ;
EchoResponse response ;
ClientContext context ;
context . set_credentials ( processor - > GetCompatibleClientCreds ( ) ) ;
request . set_message ( " Hello " ) ;
request . mutable_param ( ) - > set_echo_metadata ( true ) ;
request . mutable_param ( ) - > set_expected_client_identity (
TestAuthMetadataProcessor : : kGoodGuy ) ;
Status s = stub_ - > Echo ( & context , request , & response ) ;
EXPECT_EQ ( request . message ( ) , response . message ( ) ) ;
EXPECT_TRUE ( s . ok ( ) ) ;
// Metadata should have been consumed by the processor.
EXPECT_FALSE ( MetadataContains (
context . GetServerTrailingMetadata ( ) , GRPC_AUTHORIZATION_METADATA_KEY ,
grpc : : string ( " Bearer " ) + TestAuthMetadataProcessor : : kGoodGuy ) ) ;
}
TEST_F ( End2endTest , NonBlockingAuthMetadataProcessorFailure ) {
auto * processor = new TestAuthMetadataProcessor ( false ) ;
StartServer ( std : : shared_ptr < AuthMetadataProcessor > ( processor ) ) ;
ResetStub ( false ) ;
EchoRequest request ;
EchoResponse response ;
ClientContext context ;
context . set_credentials ( processor - > GetIncompatibleClientCreds ( ) ) ;
request . set_message ( " Hello " ) ;
Status s = stub_ - > Echo ( & context , request , & response ) ;
EXPECT_FALSE ( s . ok ( ) ) ;
EXPECT_EQ ( s . error_code ( ) , StatusCode : : UNAUTHENTICATED ) ;
}
TEST_F ( End2endTest , BlockingAuthMetadataProcessorSuccess ) {
auto * processor = new TestAuthMetadataProcessor ( true ) ;
StartServer ( std : : shared_ptr < AuthMetadataProcessor > ( processor ) ) ;
ResetStub ( false ) ;
EchoRequest request ;
EchoResponse response ;
ClientContext context ;
context . set_credentials ( processor - > GetCompatibleClientCreds ( ) ) ;
request . set_message ( " Hello " ) ;
request . mutable_param ( ) - > set_echo_metadata ( true ) ;
request . mutable_param ( ) - > set_expected_client_identity (
TestAuthMetadataProcessor : : kGoodGuy ) ;
Status s = stub_ - > Echo ( & context , request , & response ) ;
EXPECT_EQ ( request . message ( ) , response . message ( ) ) ;
EXPECT_TRUE ( s . ok ( ) ) ;
// Metadata should have been consumed by the processor.
EXPECT_FALSE ( MetadataContains (
context . GetServerTrailingMetadata ( ) , GRPC_AUTHORIZATION_METADATA_KEY ,
grpc : : string ( " Bearer " ) + TestAuthMetadataProcessor : : kGoodGuy ) ) ;
}
TEST_F ( End2endTest , BlockingAuthMetadataProcessorFailure ) {
auto * processor = new TestAuthMetadataProcessor ( true ) ;
StartServer ( std : : shared_ptr < AuthMetadataProcessor > ( processor ) ) ;
ResetStub ( false ) ;
EchoRequest request ;
EchoResponse response ;
ClientContext context ;
context . set_credentials ( processor - > GetIncompatibleClientCreds ( ) ) ;
request . set_message ( " Hello " ) ;
Status s = stub_ - > Echo ( & context , request , & response ) ;
EXPECT_FALSE ( s . ok ( ) ) ;
EXPECT_EQ ( s . error_code ( ) , StatusCode : : UNAUTHENTICATED ) ;
}
// Client sends 20 requests and the server returns CANCELLED status after
// reading 10 requests.
TEST_F ( End2endTest , RequestStreamServerEarlyCancelTest ) {