Skip to content

Commit

Permalink
Merge branch 'master' into expose_channel
Browse files Browse the repository at this point in the history
  • Loading branch information
remingtonc committed May 27, 2020
2 parents 1542839 + c09f40e commit 35f25d0
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 43 deletions.
2 changes: 1 addition & 1 deletion src/cisco_gnmi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
from .xe import XEClient
from .builder import ClientBuilder

__version__ = "1.0.8"
__version__ = "1.0.9"
97 changes: 65 additions & 32 deletions src/cisco_gnmi/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,25 @@ def set_secure(
-------
self
"""
self.__secure = True
self.__root_certificates = root_certificates
self.__private_key = private_key
self.__certificate_chain = certificate_chain
return self

def _set_insecure(self):
"""Sets the flag to use an insecure channel.
THIS IS AGAINST SPECIFICATION and should not
be used unless necessary and secure transport
is already well understood.
Returns
-------
self
"""
self.__secure = False
return self

def set_secure_from_file(
self, root_certificates=None, private_key=None, certificate_chain=None
):
Expand Down Expand Up @@ -276,44 +290,62 @@ def construct(self, return_channel=False):
Client or NXClient or XEClient or XRClient
"""
channel = None
channel_ssl_creds = None
channel_metadata_creds = None
channel_creds = None
channel_ssl_creds = grpc.ssl_channel_credentials(
self.__root_certificates, self.__private_key, self.__certificate_chain
)
if self.__username and self.__password:
LOGGER.debug("Using username/password call authentication.")
channel_metadata_creds = grpc.metadata_call_credentials(
CiscoAuthPlugin(self.__username, self.__password)
)
if channel_ssl_creds and channel_metadata_creds:
LOGGER.debug("Using SSL/metadata authentication composite credentials.")
channel_creds = grpc.composite_channel_credentials(
channel_ssl_creds, channel_metadata_creds
if self.__secure:
LOGGER.debug("Using secure channel.")
channel_metadata_creds = None
if self.__username and self.__password:
LOGGER.debug("Using username/password call authentication.")
channel_metadata_creds = grpc.metadata_call_credentials(
CiscoAuthPlugin(self.__username, self.__password)
)
channel_ssl_creds = grpc.ssl_channel_credentials(
self.__root_certificates, self.__private_key, self.__certificate_chain
)
else:
LOGGER.debug("Using SSL credentials, no metadata authentication.")
channel_creds = channel_ssl_creds
if self.__ssl_target_name_override is not False:
if self.__ssl_target_name_override is None:
if not self.__root_certificates:
raise Exception("Deriving override requires root certificate!")
self.__ssl_target_name_override = get_cn_from_cert(
self.__root_certificates
channel_creds = None
if channel_ssl_creds and channel_metadata_creds:
LOGGER.debug("Using SSL/metadata authentication composite credentials.")
channel_creds = grpc.composite_channel_credentials(
channel_ssl_creds, channel_metadata_creds
)
else:
LOGGER.debug(
"Using SSL credentials, no channel metadata authentication."
)
LOGGER.warning(
"Overriding SSL option from certificate could increase MITM susceptibility!"
channel_creds = channel_ssl_creds
if self.__ssl_target_name_override is not False:
if self.__ssl_target_name_override is None:
if not self.__root_certificates:
raise Exception("Deriving override requires root certificate!")
self.__ssl_target_name_override = get_cn_from_cert(
self.__root_certificates
)
LOGGER.warning(
"Overriding SSL option from certificate could increase MITM susceptibility!"
)
self.set_channel_option(
"grpc.ssl_target_name_override", self.__ssl_target_name_override
)
self.set_channel_option(
"grpc.ssl_target_name_override", self.__ssl_target_name_override
channel = grpc.secure_channel(
self.__target_netloc.netloc, channel_creds, self.__channel_options
)
channel = grpc.secure_channel(
self.__target_netloc.netloc, channel_creds, self.__channel_options
)
else:
LOGGER.warning(
"Insecure gRPC channel is against gNMI specification, personal data may be compromised."
)
channel = grpc.insecure_channel(self.__target_netloc.netloc)
if self.__client_class is None:
self.set_os()
client = self.__client_class(channel)
client = None
if self.__secure:
client = self.__client_class(channel)
else:
client = self.__client_class(
channel,
default_call_metadata=[
("username", self.__username),
("password", self.__password),
],
)
self._reset()
if return_channel:
return client, channel
Expand All @@ -336,4 +368,5 @@ def _reset(self):
self.__password = None
self.__channel_options = None
self.__ssl_target_name_override = False
self.__secure = True
return self
5 changes: 4 additions & 1 deletion src/cisco_gnmi/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@ def __gen_client(args):
builder = ClientBuilder(args.netloc)
builder.set_os(args.os)
builder.set_call_authentication(args.username, args.password)
if not any([args.root_certificates, args.private_key, args.certificate_chain]):
if args.insecure:
builder._set_insecure()
elif not any([args.root_certificates, args.private_key, args.certificate_chain]):
builder.set_secure_from_target()
else:
builder.set_secure_from_file(
Expand Down Expand Up @@ -339,6 +341,7 @@ def __common_args_handler(parser):
action="store_true",
)
parser.add_argument("-debug", help="Print debug messages.", action="store_true")
parser.add_argument("-insecure", help=argparse.SUPPRESS, action="store_true")
args = parser.parse_args(sys.argv[2:])
logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO)
args.username = input("Username: ")
Expand Down
20 changes: 11 additions & 9 deletions src/cisco_gnmi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,21 @@ class Client(object):
# gNMI uses nanoseconds, baseline to seconds
_NS_IN_S = int(1e9)

def __init__(self, grpc_channel, timeout=_C_MAX_LONG):
def __init__(self, grpc_channel, timeout=_C_MAX_LONG, default_call_metadata=None):
"""gNMI initialization wrapper which simply wraps some aspects of the gNMI stub.
Parameters
----------
grpc_channel : grpc.Channel
The gRPC channel to initialize the gNMI stub with.
Use ClientBuilder if unfamiliar with gRPC.
username : str
Username to authenticate gNMI RPCs.
password : str
Password to authenticate gNMI RPCs.
timeout : uint
Timeout for gRPC functionality.
default_call_metadata : list
Metadata to be sent with each gRPC call.
"""
self.service = proto.gnmi_pb2_grpc.gNMIStub(grpc_channel)
self.default_call_metadata = default_call_metadata
self._channel = grpc_channel

def capabilities(self):
Expand All @@ -115,7 +114,9 @@ def capabilities(self):
"""
message = proto.gnmi_pb2.CapabilityRequest()
LOGGER.debug(str(message))
response = self.service.Capabilities(message)
response = self.service.Capabilities(
message, metadata=self.default_call_metadata
)
return response

def get(
Expand Down Expand Up @@ -172,7 +173,7 @@ def get(

LOGGER.debug(str(request))

get_response = self.service.Get(request)
get_response = self.service.Get(request, metadata=self.default_call_metadata)
return get_response

def set(
Expand Down Expand Up @@ -219,7 +220,7 @@ def set(

LOGGER.debug(str(request))

response = self.service.Set(request)
response = self.service.Set(request, metadata=self.default_call_metadata)
return response

def subscribe(self, request_iter, extensions=None):
Expand Down Expand Up @@ -262,7 +263,8 @@ def validate_request(request):
return subscribe_request

response_stream = self.service.Subscribe(
(validate_request(request) for request in request_iter)
(validate_request(request) for request in request_iter),
metadata=self.default_call_metadata,
)
return response_stream

Expand Down

0 comments on commit 35f25d0

Please sign in to comment.