Site icon Karneliuk

pygnmi 8. Securing the gNMI connectivity with self-signed certificates.

Hello my friend,

Continuing our explanation of the pyGNMI, we’ll take a loon into the security aspect of the tool. Namely, we will take a look how quickly and easily you can implement the encryption between your host running pyGNMI and the gNMI speaking network function.


1
2
3
4
5
No part of this blogpost could be reproduced, stored in a
retrieval system, or transmitted in any form or by any
means, electronic, mechanical or photocopying, recording,
or otherwise, for commercial purposes without the
prior permission of the author.

Where is the GNMI in the Network Automation?

The automation world (network and not only) can at a high level be split into text-based automation and model-driven automation. The text based automation is all about Linux systems, where we typically template the whole configuration files, put them in the corresponding folders and then restart daemons. The model driven approach is where we communicate with the network devices using the NETCONF, RESTCONF or gNMI based on the YANG modules. At the current moment, gNMI is most dynamically developing protocol. We not only teaches you how it works and when to use it, but we also created a Python library, which significantly simplifies that process for you!

At our trainings, advanced network automation and automation with Nornir (2nd step after advanced network automation), we give you detailed knowledge of all the technologies relevant:

Moreover, we put all mentions technologies in the context of the real use cases, which our team has solved and are solving in various projects in the service providers, enterprise and data centre networks and systems across the Europe and USA. That gives you opportunity to ask questions to understand the solutions in-depts and have discussions about your own projects. And on top of that, each technology is provided with online demos and you are doing the lab afterwards to master your skills. Such a mixture creates a unique learning environment, which all students value so much. Join us and unleash your potential.

Start your automation training today.

Brief description

In our security blogposts we have recently explained how you can build the proper PKI in your lab network to make sure the communications between your applications using the HTTP, gRPC and even IP (over IPSec) are properly authenticated and encrypted. However, we understand that in multiple cases you would like to skip that process, despite it is quite simple as all you need is just a Docker, Alpine Linux and OpenSSL. Therefore, we decided to share with you how you can use the self-signed certificate from your device to develop the automation with gNMI in Python.

The self-signed certificate means that you can generate it directly on your network function (e.g., your Nokia SR OS based, Cisco IOS XR, Arita EOS, Juniper Junos, etc. – based routers) and you don’t need to use PKI. For sure, from the security standpoint this not recommended setup, as the peer can’t verify whether the endpoint is authentic. In the same time, the communication channel will still be encrypted, which means that information is being secured during transmission. As such, self-signed certificates are better than no certificates at all.

The underlying library we are using is GRPC created initially by Google. This library doesn’t allow you to skip the certificate validation in Python, how it is possible in other HTTP-related libraries in Python (e.g., requests or aiohttp). In the same time, it has a function called grpc.ssl_target_name_override, which allows to alter the subject of check in the SSL certificate. This approach let us to modify the check for the certificates, including the self-signed, and successfully use them in the environment without PKI.

Usage

There are a few steps you need to follow to have the pyGNMI working with the self-signed certificate.

  1. Create the self-signed certificate on your network device or use the one, which is shipped by default with it.
  2. Copy the certificate to your host with pyGNMI.
  3. Use it with the pyGNMI based script.
  4. Add the override function to match the subject name inside the certificate.
  5. Test the exection.

Let’s go these steps through together.

#1. Obtaining the self-signed certificate on the network function

The example of the network function we are going to use will be Arista. However, our customers has already tested that with Cisco IOS XR and Juniper JUNOS and confirmed it works for them with the self-signed certificates as well.

The process of the generating of the self-signed certificate is out of the scope for the article. But you can check how to build full PKI.

So find active certificate:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
EOS1#show management security ssl certificate PYGNMI_SELF_CERT
Certificate PYGNMI_SELF_CERT:
   Version:                   3
   Serial Number:             b9cd56ea426ef0ff
   Issuer:                    
      Common name:            EOS1
   Validity:                  
      Not before:             Mar 07 11:08:39 2021 GMT
      Not After:              Mar 07 11:08:39 2022 GMT
   Subject:                  
      Common name:            EOS1
   Subject public key info:  
      Encryption Algorithm:   RSA
      Size:                   4096 bits
      Public exponent:        65537
      Modulus:                96eb191c65a90e5b625fa4fdf52bc5bfb7e81e8fb4a78b6dc055cf5
3e481daba879a54af80deba1da426f956f2a7ab5c5c7ae4d81b9f27
7c03bd053d76b930081302067c9745d9c0d2007da7e70cec456e5e4
2e4e2896cd0f987de2c33a6aae1135a6ec652f2d4fd4d87fb8cb974
ebc7b4542c48cfe17e9cd0043dc561eb8e271cb87e42e7851e0a3fb
c04ed59cc011db9d90dcb32d5d527f139ec3a6c0887dbe201daa5fd
1ed72d7f74f1964dea0c255caeebc66fb5ca60323c842aa49d5ac34
2f4a48c03a35365f5ba29af2361a18c0d6a7a328381b3d48911a27a
d3ba99fd97b9362b02cf7a74a0ae14b960cf8882843bc41850bada8
0189984b852d178ec833cb064ad914b5da2fa7d34da76c5a3edb9b5
26fb658d70f4b31ed09b4e847f16379925d0402be3d6e3812729490
d047de2c93a68be6e4df5531f03b467199ee36cba7e90e3b98e8571
86c391ed94abf347367f8a3708b8352532b4b161152daaf6f2a6e67
25540cb4eadf9345d7e28100f0706c4bbecfe30d0e0195b047b3ef7
0384a9a3d3c7c9ce71b00730a6c133d2461a7a26911c49d4b8384a3
04fa4758c3c3ff5c0487ce425dcec36802a61f0e756b6059d1cd14c
8e48955f81565f8dd3bb1df51a376d994fb70f19f5c9313a83e30c8
08459e7a63aa5c7e1ca6360501b1713732be0dd027966e812f60f87
5421d22a10c42ebe1dcfd1d8adf9c5c539

Find its file:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[aaa@EOS1 ~]$ cat /persist/secure/ssl/certs/PYGNMI_SELF_CERT
-----BEGIN CERTIFICATE-----
MIIEozCCAougAwIBAgIJALnNVupCbvD/MA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
BAMMBkVPUzQyNTAeFw0yMTAzMTExMTA4MzlaFw0yMjAzMTExMTA4MzlaMBExDzAN
BgNVBAMMBkVPUzQyNTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJbr
GRxlqQ5bYl+k/fUrxb+36B6PtKeLbcBVz1Pkgdq6h5pUr4Deuh2kJvlW8qerXFx6
5Ngbnyd8A70FPXa5MAgTAgZ8l0XZwNIAfafnDOxFbl5C5OKJbND5h94sM6aq4RNa
bsZS8tT9TYf7jLl068e0VCxIz+F+nNAEPcVh644nHLh+QueFHgo/vATtWcwBHbnZ
Dcsy1dUn8TnsOmwIh9viAdql/R7XLX908ZZN6gwlXK7rxm+1ymAyPIQqpJ1aw0L0
pIwDo1Nl9bopryNhoYwNanoyg4Gz1IkRonrTupn9l7k2KwLPenSgrhS5YM+IgoQ7
xBhQutqAGJmEuFLReOyDPLBkrZFLXaL6fTTadsWj7bm1JvtljXD0sx7Qm06EfxY3
mSXQQCvj1uOBJylJDQR94sk6aL5uTfVTHwO0Zxme42y6fpDjuY6FcYbDke2Uq/NH
Nn+KNwi4NSUytLFhFS2q9vKm5nJVQMtOrfk0XX4oEA8HBsS77P4w0OAZWwR7PvcD
hKmj08fJznGwBzCmwTPSRhp6JpEcSdS4OEowT6R1jDw/9cBIfOQl3Ow2gCph8OdW
tgWdHNFMjkiVX4FWX43Tux31GjdtmU+3Dxn1yTE6g+MMgIRZ56Y6pcfhymNgUBsX
E3Mr4N0CeWboEvYPh1Qh0ioQxC6+Hc/R2K35xcU5AgMBAAEwDQYJKoZIhvcNAQEL
BQADggIBADGIX/QQFvUNrRwi/+IPRpb+FHISczkICA5IYrx4Mq5MHOTQFfH3uSjj
seTx4htRVPHa/6jHTcsVOe8IoT/QBjr4tabRV1D+oZCyD9gq0gPK4iO8Dkgb1v1s
X9flfatWtMaOaWIJfFtlaRuVCuHIjr4NO/MKMYRuVWtpA0YVx+J+urAzfMtefD6c
bMmdjdCfX5rTUfaV1OQ/ItAKoEq9UMLY86WCGb/tcrMmQpwutJkKqYD97u4CiQUo
Rpf8ipBKsL8nxtize/OTsLU/Npvoir1OogBOJmyK2kSxNzLpIM4JZN7HITfavEzG
G3vwWAZ/2hbaniW/flhJLZiPntA2EZwwfcFfp8ho/Dmvg0cPxIge/0S8sxUHU2Jx
Gah53kAetz2b5kNi3HuRYmOdttOGGCWRZv5aZHozx4eCVTmoJFg50Oqqo5YXTlRN
YXdqGB3UBAHb4CmmD48KdB2WJq7ltBFfXPMUdt7s/jnyyeiKwlgMd8UrCMqPGrim
1RBlQot59iPlTCvpI/7e9xsjJQnbz6tE8U/AQyrCdlEVgwQD56hmM9QVwHbAnFni
eYKhtIO5EUtCi0LM+SLLfCIXwqtOTqWG+5uuYt2AXlVMa5z2buG8pppQmU+Mob3M
bNdAKUoWgZ3oFSzBD6tdmRzJRaJoz+0bzoJQdKhuWEQ0CWmrE7Gr
-----END CERTIFICATE-----

The first step is complete.

#2. Placing it on the pyGNMI host

Now copy the content of the certificate to your host with pyGNMI and place it in some folder under meaningful name. For example, let’s call the folder the cert and and the file after the network device hostname EOS1:


1
2
3
4
+--pygnmi_test
   +--cert
   |  +--EOS1.pem
   +--gnmi_get.py

Inside the file copy the content of the file with the certificate you found on the device:


1
2
3
4
5
$ cat cert/EOS1.pem
-----BEGIN CERTIFICATE-----
MIIEozCCAougAwIBAgIJALnNVupCbvD/MA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
!
! Further output is truncated for brevity

The second step is complete is well

#3. Using the certificate inside the script

Create the Python script using the pyGNMI to interact with the network device. We have taken one of the official examples you can find in your GitHub repository and added the path towards the certificate:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python

# Modules
from pygnmi.client import gNMIclient

# Variables
from inventory import hosts
pc = "./cert/device.pem"

# Body
if __name__ == "__main__":
    paths = ['openconfig-interfaces:interfaces', 'openconfig-network-instance:network-instances']

    for host in hosts:
        with gNMIclient(target=(host["ip_address"], host["port"]), username=host["username"],
                        password=host["password"], path_cert=pc) as gc:
            result = gc.get(path=paths, encoding='json')
            print(f"{host['ip_address']}: {result}\n\n")

The path to the certificate the is added in the variable pc, which is then used as a value for the argument path_cert inside the gNMIclient object. Pay attention, that the key insecure=True is not used anymore, as the channel is being now encrypted.

#4. Overriding the authentication target

Finally, in the override argument is added to the gNMIclient class. Within the inventory file, we are using the IP address per our topology to reach the network devices, so the connection is done based on the IP, whereas the certificate contains the hostname. Hence, override is needed (only the object instantiation part is shown):


1
2
3
4
...
        with gNMIclient(target=(host["ip_address"], host["port"]), username=host["username"],
                        password=host["password"], path_cert=pc, override="EOS1") as gc:
...

The override argument will set correspondingly the argument for the certificate validation and certificate check for the self-signed certificate will be passed.

#5. Testing the script

Once the script is complete, meaning you have certificate and you have set the override correctly, you can access the device:


1
2
3
4
$ ./gnmi_get.py
192.168.100.10: {'notification': [{'timestamp': 0, 'update': [{'path': 'interfaces', 'val': {'openconfig-interfaces:interface': [{'config': {'description': '', 'enabled': True, 'arista-intf-augments:load-interval': 300, 'loopbac...
!
! Further output is truncated for brevity.

So, the gNMI communication with certificate works SUCCESSFULLY.

If you know tries to use the original script (WITHOUT certificate):


1
2
3
4
...
        with gNMIclient(target=(host["ip_address"], host["port"]), username=host["username"],
                        password=host["password"], insecure=True) as gc:
...

Then you will get the timeout:


1
2
3
4
5
6
7
8
9
10
$ ./gnmi_get.py
Traceback (most recent call last):
  File "./gnmi_get.py", line 17, in <module>
    with gNMIclient(target=(host["ip_address"], host["port"]), username=host["username"],
  File "/home/aaa/Dev/self_test/venv/lib/python3.8/site-packages/pygnmi/client.py", line 50, in __enter__
    grpc.channel_ready_future(self.__channel).result(timeout=5)
  File "/home/aaa/Dev/self_test/venv/lib/python3.8/site-packages/grpc/_utilities.py", line 140, in result
    self._block(timeout)
  File "/home/aaa/Dev/self_test/venv/lib/python3.8/site-packages/grpc/_utilities.py", line 86, in _block
    raise grpc.FutureTimeoutError()

So script, as it supposed to be, doesn’t work.

And at in our training you can learn much more about gNMI, its use cases, and learn how to write your own scripts using that.

GitHub and PyPI

You can see this and others examples of the pygnmi usage in our GitHub repository. Moreover, it is also available in PyPI, what makes the installation process very easy.

If you prefer video

You can watch this demo on our YouTube channel:

Lessons learned

In fact, originally we were planning to show how to use the pyGNMI with the PKI and even created the explanations how to set up the PKI and how to integrate network and Linux devices to that. However, given we have received quite a few requests for clarifications how to use the self-signed certificates, we decided to first covers that point.

Conclusion

As more and more companies starts adopting the use of the gNMI for monitoring and management of the network infrastructure, the pyGNMI helps you a lot to benefit the whole power of Python for automation without the necessity to understand protocol buffers and Python Meta Classes on the deep level. You can continue to be a network and netdevops engineer and be successful leveraging the pyGNMI in your day today activities, as it can help to build you both secure and not-secure (depending on your needs) connections to your network devices. Take care and good bye.

Support us





P.S.

If you have further questions or you need help with your networks, we are happy to assist you, just send us a message. Also don’t forget to share the article on your social media, if you like it.

BR,

Anton Karneliuk

Exit mobile version