|
|
|
@ -352,6 +352,85 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
############ Authentication & Authorization Interfaces & Classes ############# |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ChannelCredentials(object): |
|
|
|
|
"""A value encapsulating the data required to create a secure Channel. |
|
|
|
|
|
|
|
|
|
This class has no supported interface - it exists to define the type of its |
|
|
|
|
instances and its instances exist to be passed to other functions. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self, credentials): |
|
|
|
|
self._credentials = credentials |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CallCredentials(object): |
|
|
|
|
"""A value encapsulating data asserting an identity over a channel. |
|
|
|
|
|
|
|
|
|
A CallCredentials may be composed with ChannelCredentials to always assert |
|
|
|
|
identity for every call over that Channel. |
|
|
|
|
|
|
|
|
|
This class has no supported interface - it exists to define the type of its |
|
|
|
|
instances and its instances exist to be passed to other functions. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self, credentials): |
|
|
|
|
self._credentials = credentials |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AuthMetadataContext(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""Provides information to call credentials metadata plugins. |
|
|
|
|
|
|
|
|
|
Attributes: |
|
|
|
|
service_url: A string URL of the service being called into. |
|
|
|
|
method_name: A string of the fully qualified method name being called. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AuthMetadataPluginCallback(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""Callback object received by a metadata plugin.""" |
|
|
|
|
|
|
|
|
|
def __call__(self, metadata, error): |
|
|
|
|
"""Inform the gRPC runtime of the metadata to construct a CallCredentials. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
metadata: An iterable of 2-sequences (e.g. tuples) of metadata key/value |
|
|
|
|
pairs. |
|
|
|
|
error: An Exception to indicate error or None to indicate success. |
|
|
|
|
""" |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AuthMetadataPlugin(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""A specification for custom authentication.""" |
|
|
|
|
|
|
|
|
|
def __call__(self, context, callback): |
|
|
|
|
"""Implements authentication by passing metadata to a callback. |
|
|
|
|
|
|
|
|
|
Implementations of this method must not block. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
context: An AuthMetadataContext providing information on the RPC that the |
|
|
|
|
plugin is being called to authenticate. |
|
|
|
|
callback: An AuthMetadataPluginCallback to be invoked either synchronously |
|
|
|
|
or asynchronously. |
|
|
|
|
""" |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ServerCredentials(object): |
|
|
|
|
"""A value encapsulating the data required to open a secure port on a Server. |
|
|
|
|
|
|
|
|
|
This class has no supported interface - it exists to define the type of its |
|
|
|
|
instances and its instances exist to be passed to other functions. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self, credentials): |
|
|
|
|
self._credentials = credentials |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
######################## Multi-Callable Interfaces ########################### |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -359,7 +438,9 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""Affords invoking a unary-unary RPC.""" |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def __call__(self, request, timeout=None, metadata=None, with_call=False): |
|
|
|
|
def __call__( |
|
|
|
|
self, request, timeout=None, metadata=None, credentials=None, |
|
|
|
|
with_call=False): |
|
|
|
|
"""Synchronously invokes the underlying RPC. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -367,6 +448,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
timeout: An optional duration of time in seconds to allow for the RPC. |
|
|
|
|
metadata: An optional sequence of pairs of bytes to be transmitted to the |
|
|
|
|
service-side of the RPC. |
|
|
|
|
credentials: An optional CallCredentials for the RPC. |
|
|
|
|
with_call: Whether or not to include return a Call for the RPC in addition |
|
|
|
|
to the response. |
|
|
|
|
|
|
|
|
@ -382,7 +464,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def future(self, request, timeout=None, metadata=None): |
|
|
|
|
def future(self, request, timeout=None, metadata=None, credentials=None): |
|
|
|
|
"""Asynchronously invokes the underlying RPC. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -390,6 +472,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
timeout: An optional duration of time in seconds to allow for the RPC. |
|
|
|
|
metadata: An optional sequence of pairs of bytes to be transmitted to the |
|
|
|
|
service-side of the RPC. |
|
|
|
|
credentials: An optional CallCredentials for the RPC. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
An object that is both a Call for the RPC and a Future. In the event of |
|
|
|
@ -404,7 +487,7 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""Affords invoking a unary-stream RPC.""" |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def __call__(self, request, timeout=None, metadata=None): |
|
|
|
|
def __call__(self, request, timeout=None, metadata=None, credentials=None): |
|
|
|
|
"""Invokes the underlying RPC. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -412,6 +495,7 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
timeout: An optional duration of time in seconds to allow for the RPC. |
|
|
|
|
metadata: An optional sequence of pairs of bytes to be transmitted to the |
|
|
|
|
service-side of the RPC. |
|
|
|
|
credentials: An optional CallCredentials for the RPC. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
An object that is both a Call for the RPC and an iterator of response |
|
|
|
@ -426,7 +510,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def __call__( |
|
|
|
|
self, request_iterator, timeout=None, metadata=None, with_call=False): |
|
|
|
|
self, request_iterator, timeout=None, metadata=None, credentials=None, |
|
|
|
|
with_call=False): |
|
|
|
|
"""Synchronously invokes the underlying RPC. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -434,6 +519,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
timeout: An optional duration of time in seconds to allow for the RPC. |
|
|
|
|
metadata: An optional sequence of pairs of bytes to be transmitted to the |
|
|
|
|
service-side of the RPC. |
|
|
|
|
credentials: An optional CallCredentials for the RPC. |
|
|
|
|
with_call: Whether or not to include return a Call for the RPC in addition |
|
|
|
|
to the response. |
|
|
|
|
|
|
|
|
@ -449,7 +535,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def future(self, request_iterator, timeout=None, metadata=None): |
|
|
|
|
def future( |
|
|
|
|
self, request_iterator, timeout=None, metadata=None, credentials=None): |
|
|
|
|
"""Asynchronously invokes the underlying RPC. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -457,6 +544,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
timeout: An optional duration of time in seconds to allow for the RPC. |
|
|
|
|
metadata: An optional sequence of pairs of bytes to be transmitted to the |
|
|
|
|
service-side of the RPC. |
|
|
|
|
credentials: An optional CallCredentials for the RPC. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
An object that is both a Call for the RPC and a Future. In the event of |
|
|
|
@ -471,7 +559,8 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""Affords invoking a stream-stream RPC in any call style.""" |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def __call__(self, request_iterator, timeout=None, metadata=None): |
|
|
|
|
def __call__( |
|
|
|
|
self, request_iterator, timeout=None, metadata=None, credentials=None): |
|
|
|
|
"""Invokes the underlying RPC. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -479,6 +568,7 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
timeout: An optional duration of time in seconds to allow for the RPC. |
|
|
|
|
metadata: An optional sequence of pairs of bytes to be transmitted to the |
|
|
|
|
service-side of the RPC. |
|
|
|
|
credentials: An optional CallCredentials for the RPC. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
An object that is both a Call for the RPC and an iterator of response |
|
|
|
@ -690,7 +780,6 @@ class RpcMethodHandler(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
|
|
|
|
|
class HandlerCallDetails(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
"""Describes an RPC that has just arrived for service. |
|
|
|
|
|
|
|
|
|
Attributes: |
|
|
|
|
method: The method name of the RPC. |
|
|
|
|
invocation_metadata: The metadata from the invocation side of the RPC. |
|
|
|
@ -750,6 +839,25 @@ class Server(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
""" |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def add_secure_port(self, address, server_credentials): |
|
|
|
|
"""Reserves a port for secure RPC service after this Server becomes active. |
|
|
|
|
|
|
|
|
|
This method may only be called before calling this Server's start method is |
|
|
|
|
called. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
address: The address for which to open a port. |
|
|
|
|
server_credentials: A ServerCredentials. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
An integer port on which RPCs will be serviced after this link has been |
|
|
|
|
started. This is typically the same number as the port number contained |
|
|
|
|
in the passed address, but will likely be different if the port number |
|
|
|
|
contained in the passed address was zero. |
|
|
|
|
""" |
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
@abc.abstractmethod |
|
|
|
|
def start(self): |
|
|
|
|
"""Starts this Server's service of RPCs. |
|
|
|
@ -792,6 +900,120 @@ class Server(six.with_metaclass(abc.ABCMeta)): |
|
|
|
|
################################# Functions ################################ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ssl_channel_credentials( |
|
|
|
|
root_certificates=None, private_key=None, certificate_chain=None): |
|
|
|
|
"""Creates a ChannelCredentials for use with an SSL-enabled Channel. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
root_certificates: The PEM-encoded root certificates or unset to ask for |
|
|
|
|
them to be retrieved from a default location. |
|
|
|
|
private_key: The PEM-encoded private key to use or unset if no private key |
|
|
|
|
should be used. |
|
|
|
|
certificate_chain: The PEM-encoded certificate chain to use or unset if no |
|
|
|
|
certificate chain should be used. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A ChannelCredentials for use with an SSL-enabled Channel. |
|
|
|
|
""" |
|
|
|
|
if private_key is not None or certificate_chain is not None: |
|
|
|
|
pair = _cygrpc.SslPemKeyCertPair(private_key, certificate_chain) |
|
|
|
|
else: |
|
|
|
|
pair = None |
|
|
|
|
return ChannelCredentials( |
|
|
|
|
_cygrpc.channel_credentials_ssl(root_certificates, pair)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def metadata_call_credentials(metadata_plugin, name=None): |
|
|
|
|
"""Construct CallCredentials from an AuthMetadataPlugin. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
metadata_plugin: An AuthMetadataPlugin to use as the authentication behavior |
|
|
|
|
in the created CallCredentials. |
|
|
|
|
name: A name for the plugin. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A CallCredentials. |
|
|
|
|
""" |
|
|
|
|
from grpc import _plugin_wrapping |
|
|
|
|
if name is None: |
|
|
|
|
try: |
|
|
|
|
effective_name = metadata_plugin.__name__ |
|
|
|
|
except AttributeError: |
|
|
|
|
effective_name = metadata_plugin.__class__.__name__ |
|
|
|
|
else: |
|
|
|
|
effective_name = name |
|
|
|
|
return CallCredentials( |
|
|
|
|
_plugin_wrapping.call_credentials_metadata_plugin( |
|
|
|
|
metadata_plugin, effective_name)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def composite_call_credentials(call_credentials, additional_call_credentials): |
|
|
|
|
"""Compose two CallCredentials to make a new one. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
call_credentials: A CallCredentials object. |
|
|
|
|
additional_call_credentials: Another CallCredentials object to compose on |
|
|
|
|
top of call_credentials. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A new CallCredentials composed of the two given CallCredentials. |
|
|
|
|
""" |
|
|
|
|
return CallCredentials( |
|
|
|
|
_cygrpc.call_credentials_composite( |
|
|
|
|
call_credentials._credentials, |
|
|
|
|
additional_call_credentials._credentials)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def composite_channel_credentials(channel_credentials, call_credentials): |
|
|
|
|
"""Compose a ChannelCredentials and a CallCredentials. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
channel_credentials: A ChannelCredentials. |
|
|
|
|
call_credentials: A CallCredentials. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A ChannelCredentials composed of the given ChannelCredentials and |
|
|
|
|
CallCredentials. |
|
|
|
|
""" |
|
|
|
|
return ChannelCredentials( |
|
|
|
|
_cygrpc.channel_credentials_composite( |
|
|
|
|
channel_credentials._credentials, call_credentials._credentials)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ssl_server_credentials( |
|
|
|
|
private_key_certificate_chain_pairs, root_certificates=None, |
|
|
|
|
require_client_auth=False): |
|
|
|
|
"""Creates a ServerCredentials for use with an SSL-enabled Server. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
private_key_certificate_chain_pairs: A nonempty sequence each element of |
|
|
|
|
which is a pair the first element of which is a PEM-encoded private key |
|
|
|
|
and the second element of which is the corresponding PEM-encoded |
|
|
|
|
certificate chain. |
|
|
|
|
root_certificates: PEM-encoded client root certificates to be used for |
|
|
|
|
verifying authenticated clients. If omitted, require_client_auth must also |
|
|
|
|
be omitted or be False. |
|
|
|
|
require_client_auth: A boolean indicating whether or not to require clients |
|
|
|
|
to be authenticated. May only be True if root_certificates is not None. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A ServerCredentials for use with an SSL-enabled Server. |
|
|
|
|
""" |
|
|
|
|
if len(private_key_certificate_chain_pairs) == 0: |
|
|
|
|
raise ValueError( |
|
|
|
|
'At least one private key-certificate chain pair is required!') |
|
|
|
|
elif require_client_auth and root_certificates is None: |
|
|
|
|
raise ValueError( |
|
|
|
|
'Illegal to require client auth without providing root certificates!') |
|
|
|
|
else: |
|
|
|
|
return ServerCredentials( |
|
|
|
|
_cygrpc.server_credentials_ssl( |
|
|
|
|
root_certificates, |
|
|
|
|
[_cygrpc.SslPemKeyCertPair(key, pem) |
|
|
|
|
for key, pem in private_key_certificate_chain_pairs], |
|
|
|
|
require_client_auth)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def channel_ready_future(channel): |
|
|
|
|
"""Creates a Future tracking when a Channel is ready. |
|
|
|
|
|
|
|
|
@ -825,6 +1047,22 @@ def insecure_channel(target, options=None): |
|
|
|
|
return _channel.Channel(target, None, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def secure_channel(target, credentials, options=None): |
|
|
|
|
"""Creates an insecure Channel to a server. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
target: The target to which to connect. |
|
|
|
|
credentials: A ChannelCredentials instance. |
|
|
|
|
options: A sequence of string-value pairs according to which to configure |
|
|
|
|
the created channel. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A Channel to the target through which RPCs may be conducted. |
|
|
|
|
""" |
|
|
|
|
from grpc import _channel |
|
|
|
|
return _channel.Channel(target, credentials, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def server(generic_rpc_handlers, thread_pool, options=None): |
|
|
|
|
"""Creates a Server with which RPCs can be serviced. |
|
|
|
|
|
|
|
|
|