• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 The gRPC Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Client of the Python example of customizing authentication mechanism."""
15
16from __future__ import absolute_import
17from __future__ import division
18from __future__ import print_function
19
20import argparse
21import contextlib
22import logging
23
24import grpc
25from examples import helloworld_pb2
26from examples import helloworld_pb2_grpc
27from examples.python.auth import _credentials
28
29_LOGGER = logging.getLogger(__name__)
30_LOGGER.setLevel(logging.INFO)
31
32_SERVER_ADDR_TEMPLATE = 'localhost:%d'
33_SIGNATURE_HEADER_KEY = 'x-signature'
34
35
36class AuthGateway(grpc.AuthMetadataPlugin):
37
38    def __call__(self, context, callback):
39        """Implements authentication by passing metadata to a callback.
40
41        Implementations of this method must not block.
42
43        Args:
44          context: An AuthMetadataContext providing information on the RPC that
45            the plugin is being called to authenticate.
46          callback: An AuthMetadataPluginCallback to be invoked either
47            synchronously or asynchronously.
48        """
49        # Example AuthMetadataContext object:
50        # AuthMetadataContext(
51        #     service_url=u'https://localhost:50051/helloworld.Greeter',
52        #     method_name=u'SayHello')
53        signature = context.method_name[::-1]
54        callback(((_SIGNATURE_HEADER_KEY, signature),), None)
55
56
57@contextlib.contextmanager
58def create_client_channel(addr):
59    # Call credential object will be invoked for every single RPC
60    call_credentials = grpc.metadata_call_credentials(AuthGateway(),
61                                                      name='auth gateway')
62    # Channel credential will be valid for the entire channel
63    channel_credential = grpc.ssl_channel_credentials(
64        _credentials.ROOT_CERTIFICATE)
65    # Combining channel credentials and call credentials together
66    composite_credentials = grpc.composite_channel_credentials(
67        channel_credential,
68        call_credentials,
69    )
70    channel = grpc.secure_channel(addr, composite_credentials)
71    yield channel
72
73
74def send_rpc(channel):
75    stub = helloworld_pb2_grpc.GreeterStub(channel)
76    request = helloworld_pb2.HelloRequest(name='you')
77    try:
78        response = stub.SayHello(request)
79    except grpc.RpcError as rpc_error:
80        _LOGGER.error('Received error: %s', rpc_error)
81        return rpc_error
82    else:
83        _LOGGER.info('Received message: %s', response)
84        return response
85
86
87def main():
88    parser = argparse.ArgumentParser()
89    parser.add_argument('--port',
90                        nargs='?',
91                        type=int,
92                        default=50051,
93                        help='the address of server')
94    args = parser.parse_args()
95
96    with create_client_channel(_SERVER_ADDR_TEMPLATE % args.port) as channel:
97        send_rpc(channel)
98
99
100if __name__ == '__main__':
101    logging.basicConfig(level=logging.INFO)
102    main()
103