Skip to content

Commit 35f25d0

Browse files
committed
Merge branch 'master' into expose_channel
2 parents 1542839 + c09f40e commit 35f25d0

File tree

4 files changed

+81
-43
lines changed

4 files changed

+81
-43
lines changed

src/cisco_gnmi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@
3030
from .xe import XEClient
3131
from .builder import ClientBuilder
3232

33-
__version__ = "1.0.8"
33+
__version__ = "1.0.9"

src/cisco_gnmi/builder.py

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,25 @@ def set_secure(
158158
-------
159159
self
160160
"""
161+
self.__secure = True
161162
self.__root_certificates = root_certificates
162163
self.__private_key = private_key
163164
self.__certificate_chain = certificate_chain
164165
return self
165166

167+
def _set_insecure(self):
168+
"""Sets the flag to use an insecure channel.
169+
THIS IS AGAINST SPECIFICATION and should not
170+
be used unless necessary and secure transport
171+
is already well understood.
172+
173+
Returns
174+
-------
175+
self
176+
"""
177+
self.__secure = False
178+
return self
179+
166180
def set_secure_from_file(
167181
self, root_certificates=None, private_key=None, certificate_chain=None
168182
):
@@ -276,44 +290,62 @@ def construct(self, return_channel=False):
276290
Client or NXClient or XEClient or XRClient
277291
"""
278292
channel = None
279-
channel_ssl_creds = None
280-
channel_metadata_creds = None
281-
channel_creds = None
282-
channel_ssl_creds = grpc.ssl_channel_credentials(
283-
self.__root_certificates, self.__private_key, self.__certificate_chain
284-
)
285-
if self.__username and self.__password:
286-
LOGGER.debug("Using username/password call authentication.")
287-
channel_metadata_creds = grpc.metadata_call_credentials(
288-
CiscoAuthPlugin(self.__username, self.__password)
289-
)
290-
if channel_ssl_creds and channel_metadata_creds:
291-
LOGGER.debug("Using SSL/metadata authentication composite credentials.")
292-
channel_creds = grpc.composite_channel_credentials(
293-
channel_ssl_creds, channel_metadata_creds
293+
if self.__secure:
294+
LOGGER.debug("Using secure channel.")
295+
channel_metadata_creds = None
296+
if self.__username and self.__password:
297+
LOGGER.debug("Using username/password call authentication.")
298+
channel_metadata_creds = grpc.metadata_call_credentials(
299+
CiscoAuthPlugin(self.__username, self.__password)
300+
)
301+
channel_ssl_creds = grpc.ssl_channel_credentials(
302+
self.__root_certificates, self.__private_key, self.__certificate_chain
294303
)
295-
else:
296-
LOGGER.debug("Using SSL credentials, no metadata authentication.")
297-
channel_creds = channel_ssl_creds
298-
if self.__ssl_target_name_override is not False:
299-
if self.__ssl_target_name_override is None:
300-
if not self.__root_certificates:
301-
raise Exception("Deriving override requires root certificate!")
302-
self.__ssl_target_name_override = get_cn_from_cert(
303-
self.__root_certificates
304+
channel_creds = None
305+
if channel_ssl_creds and channel_metadata_creds:
306+
LOGGER.debug("Using SSL/metadata authentication composite credentials.")
307+
channel_creds = grpc.composite_channel_credentials(
308+
channel_ssl_creds, channel_metadata_creds
309+
)
310+
else:
311+
LOGGER.debug(
312+
"Using SSL credentials, no channel metadata authentication."
304313
)
305-
LOGGER.warning(
306-
"Overriding SSL option from certificate could increase MITM susceptibility!"
314+
channel_creds = channel_ssl_creds
315+
if self.__ssl_target_name_override is not False:
316+
if self.__ssl_target_name_override is None:
317+
if not self.__root_certificates:
318+
raise Exception("Deriving override requires root certificate!")
319+
self.__ssl_target_name_override = get_cn_from_cert(
320+
self.__root_certificates
321+
)
322+
LOGGER.warning(
323+
"Overriding SSL option from certificate could increase MITM susceptibility!"
324+
)
325+
self.set_channel_option(
326+
"grpc.ssl_target_name_override", self.__ssl_target_name_override
307327
)
308-
self.set_channel_option(
309-
"grpc.ssl_target_name_override", self.__ssl_target_name_override
328+
channel = grpc.secure_channel(
329+
self.__target_netloc.netloc, channel_creds, self.__channel_options
310330
)
311-
channel = grpc.secure_channel(
312-
self.__target_netloc.netloc, channel_creds, self.__channel_options
313-
)
331+
else:
332+
LOGGER.warning(
333+
"Insecure gRPC channel is against gNMI specification, personal data may be compromised."
334+
)
335+
channel = grpc.insecure_channel(self.__target_netloc.netloc)
314336
if self.__client_class is None:
315337
self.set_os()
316-
client = self.__client_class(channel)
338+
client = None
339+
if self.__secure:
340+
client = self.__client_class(channel)
341+
else:
342+
client = self.__client_class(
343+
channel,
344+
default_call_metadata=[
345+
("username", self.__username),
346+
("password", self.__password),
347+
],
348+
)
317349
self._reset()
318350
if return_channel:
319351
return client, channel
@@ -336,4 +368,5 @@ def _reset(self):
336368
self.__password = None
337369
self.__channel_options = None
338370
self.__ssl_target_name_override = False
371+
self.__secure = True
339372
return self

src/cisco_gnmi/cli.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,9 @@ def __gen_client(args):
293293
builder = ClientBuilder(args.netloc)
294294
builder.set_os(args.os)
295295
builder.set_call_authentication(args.username, args.password)
296-
if not any([args.root_certificates, args.private_key, args.certificate_chain]):
296+
if args.insecure:
297+
builder._set_insecure()
298+
elif not any([args.root_certificates, args.private_key, args.certificate_chain]):
297299
builder.set_secure_from_target()
298300
else:
299301
builder.set_secure_from_file(
@@ -339,6 +341,7 @@ def __common_args_handler(parser):
339341
action="store_true",
340342
)
341343
parser.add_argument("-debug", help="Print debug messages.", action="store_true")
344+
parser.add_argument("-insecure", help=argparse.SUPPRESS, action="store_true")
342345
args = parser.parse_args(sys.argv[2:])
343346
logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO)
344347
args.username = input("Username: ")

src/cisco_gnmi/client.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,21 @@ class Client(object):
8383
# gNMI uses nanoseconds, baseline to seconds
8484
_NS_IN_S = int(1e9)
8585

86-
def __init__(self, grpc_channel, timeout=_C_MAX_LONG):
86+
def __init__(self, grpc_channel, timeout=_C_MAX_LONG, default_call_metadata=None):
8787
"""gNMI initialization wrapper which simply wraps some aspects of the gNMI stub.
8888
8989
Parameters
9090
----------
9191
grpc_channel : grpc.Channel
9292
The gRPC channel to initialize the gNMI stub with.
9393
Use ClientBuilder if unfamiliar with gRPC.
94-
username : str
95-
Username to authenticate gNMI RPCs.
96-
password : str
97-
Password to authenticate gNMI RPCs.
9894
timeout : uint
9995
Timeout for gRPC functionality.
96+
default_call_metadata : list
97+
Metadata to be sent with each gRPC call.
10098
"""
10199
self.service = proto.gnmi_pb2_grpc.gNMIStub(grpc_channel)
100+
self.default_call_metadata = default_call_metadata
102101
self._channel = grpc_channel
103102

104103
def capabilities(self):
@@ -115,7 +114,9 @@ def capabilities(self):
115114
"""
116115
message = proto.gnmi_pb2.CapabilityRequest()
117116
LOGGER.debug(str(message))
118-
response = self.service.Capabilities(message)
117+
response = self.service.Capabilities(
118+
message, metadata=self.default_call_metadata
119+
)
119120
return response
120121

121122
def get(
@@ -172,7 +173,7 @@ def get(
172173

173174
LOGGER.debug(str(request))
174175

175-
get_response = self.service.Get(request)
176+
get_response = self.service.Get(request, metadata=self.default_call_metadata)
176177
return get_response
177178

178179
def set(
@@ -219,7 +220,7 @@ def set(
219220

220221
LOGGER.debug(str(request))
221222

222-
response = self.service.Set(request)
223+
response = self.service.Set(request, metadata=self.default_call_metadata)
223224
return response
224225

225226
def subscribe(self, request_iter, extensions=None):
@@ -262,7 +263,8 @@ def validate_request(request):
262263
return subscribe_request
263264

264265
response_stream = self.service.Subscribe(
265-
(validate_request(request) for request in request_iter)
266+
(validate_request(request) for request in request_iter),
267+
metadata=self.default_call_metadata,
266268
)
267269
return response_stream
268270

0 commit comments

Comments
 (0)