Skip to content

Commit 05ce25c

Browse files
committed
Merged master from upstream
2 parents ef247c8 + 227baf7 commit 05ce25c

File tree

5 files changed

+74
-82
lines changed

5 files changed

+74
-82
lines changed

scripts/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM python:3-alpine
2+
RUN apk add --no-cache --virtual .build-deps gcc musl-dev libffi-dev openssl-dev g++
3+
RUN pip install cisco-gnmi
4+
ENTRYPOINT [ "cisco-gnmi" ]

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.10"

src/cisco_gnmi/builder.py

Lines changed: 52 additions & 71 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
):
@@ -267,7 +281,7 @@ def set_channel_option(self, name, value):
267281
self.__channel_options.append(new_option)
268282
return self
269283

270-
def construct(self):
284+
def construct(self, return_channel=False):
271285
"""Constructs and returns the desired Client object.
272286
The instance of this class will reset to default values for further building.
273287
@@ -276,36 +290,36 @@ def construct(self):
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 = None
283-
if any((self.__root_certificates, self.__private_key, self.__certificate_chain)):
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+
)
284301
channel_ssl_creds = grpc.ssl_channel_credentials(
285302
self.__root_certificates, self.__private_key, self.__certificate_chain
286303
)
287-
if self.__username and self.__password:
288-
channel_metadata_creds = grpc.metadata_call_credentials(
289-
CiscoAuthPlugin(self.__username, self.__password)
290-
)
291-
logging.debug("Using username/password call authentication.")
292-
if channel_ssl_creds and channel_metadata_creds:
293-
channel_creds = grpc.composite_channel_credentials(
294-
channel_ssl_creds, channel_metadata_creds
295-
)
296-
logging.debug("Using SSL/metadata authentication composite credentials.")
297-
elif channel_ssl_creds:
298-
channel_creds = channel_ssl_creds
299-
logging.debug("Using SSL credentials, no metadata authentication.")
300-
if channel_creds:
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."
313+
)
314+
channel_creds = channel_ssl_creds
301315
if self.__ssl_target_name_override is not False:
302316
if self.__ssl_target_name_override is None:
303317
if not self.__root_certificates:
304318
raise Exception("Deriving override requires root certificate!")
305319
self.__ssl_target_name_override = get_cn_from_cert(
306320
self.__root_certificates
307321
)
308-
logging.warning(
322+
LOGGER.warning(
309323
"Overriding SSL option from certificate could increase MITM susceptibility!"
310324
)
311325
self.set_channel_option(
@@ -315,62 +329,28 @@ def construct(self):
315329
self.__target_netloc.netloc, channel_creds, self.__channel_options
316330
)
317331
else:
332+
LOGGER.warning(
333+
"Insecure gRPC channel is against gNMI specification, personal data may be compromised."
334+
)
318335
channel = grpc.insecure_channel(self.__target_netloc.netloc)
319336
if self.__client_class is None:
320337
self.set_os()
321-
client = self.__client_class(channel)
322-
self._reset()
323-
return client
324-
325-
def save_construct(self):
326-
"""Constructs and returns the desired Client object.
327-
The instance of this class will reset to default values for further building.
328-
329-
Returns
330-
-------
331-
Client or NXClient or XEClient or XRClient
332-
"""
333-
channel = None
334-
channel_ssl_creds = None
335-
channel_metadata_creds = None
336-
channel_creds = None
337-
channel_ssl_creds = grpc.ssl_channel_credentials(
338-
self.__root_certificates, self.__private_key, self.__certificate_chain
339-
)
340-
if self.__username and self.__password:
341-
LOGGER.debug("Using username/password call authentication.")
342-
channel_metadata_creds = grpc.metadata_call_credentials(
343-
CiscoAuthPlugin(self.__username, self.__password)
344-
)
345-
if channel_ssl_creds and channel_metadata_creds:
346-
LOGGER.debug("Using SSL/metadata authentication composite credentials.")
347-
channel_creds = grpc.composite_channel_credentials(
348-
channel_ssl_creds, channel_metadata_creds
349-
)
338+
client = None
339+
if self.__secure:
340+
client = self.__client_class(channel)
350341
else:
351-
LOGGER.debug("Using SSL credentials, no metadata authentication.")
352-
channel_creds = channel_ssl_creds
353-
if self.__ssl_target_name_override is not False:
354-
if self.__ssl_target_name_override is None:
355-
if not self.__root_certificates:
356-
raise Exception("Deriving override requires root certificate!")
357-
self.__ssl_target_name_override = get_cn_from_cert(
358-
self.__root_certificates
359-
)
360-
LOGGER.warning(
361-
"Overriding SSL option from certificate could increase MITM susceptibility!"
362-
)
363-
self.set_channel_option(
364-
"grpc.ssl_target_name_override", self.__ssl_target_name_override
342+
client = self.__client_class(
343+
channel,
344+
default_call_metadata=[
345+
("username", self.__username),
346+
("password", self.__password),
347+
],
365348
)
366-
channel = grpc.secure_channel(
367-
self.__target_netloc.netloc, channel_creds, self.__channel_options
368-
)
369-
if self.__client_class is None:
370-
self.set_os()
371-
client = self.__client_class(channel)
372349
self._reset()
373-
return client
350+
if return_channel:
351+
return client, channel
352+
else:
353+
return client
374354

375355
def _reset(self):
376356
"""Resets the builder.
@@ -388,4 +368,5 @@ def _reset(self):
388368
self.__password = None
389369
self.__channel_options = None
390370
self.__ssl_target_name_override = False
371+
self.__secure = True
391372
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: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,22 @@ 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
101+
self._channel = grpc_channel
102102

103103
def capabilities(self):
104104
"""Capabilities allows the client to retrieve the set of capabilities that
@@ -114,7 +114,9 @@ def capabilities(self):
114114
"""
115115
message = proto.gnmi_pb2.CapabilityRequest()
116116
LOGGER.debug(str(message))
117-
response = self.service.Capabilities(message)
117+
response = self.service.Capabilities(
118+
message, metadata=self.default_call_metadata
119+
)
118120
return response
119121

120122
def get(
@@ -171,7 +173,7 @@ def get(
171173

172174
LOGGER.debug(str(request))
173175

174-
get_response = self.service.Get(request)
176+
get_response = self.service.Get(request, metadata=self.default_call_metadata)
175177
return get_response
176178

177179
def set(
@@ -217,7 +219,8 @@ def set(
217219
request.extension.extend(extensions)
218220

219221
LOGGER.debug(str(request))
220-
response = self.service.Set(request)
222+
223+
response = self.service.Set(request, metadata=self.default_call_metadata)
221224
return response
222225

223226
def subscribe(self, request_iter, extensions=None):
@@ -260,7 +263,8 @@ def validate_request(request):
260263
return subscribe_request
261264

262265
response_stream = self.service.Subscribe(
263-
(validate_request(request) for request in request_iter)
266+
(validate_request(request) for request in request_iter),
267+
metadata=self.default_call_metadata,
264268
)
265269
return response_stream
266270

0 commit comments

Comments
 (0)