
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-30-2020 05:11 AM
I am working on a service template part of which will generate random strings and store them in an NSO container as tailf:aes-cfb-128-encrypted-string leafs. Is there a simple way inside of python MAAPI to generate the encrypted passwords? When I just pass string values to these leafs it fails with an "item has a bad/wrong type" error.
I know that to work with items that are already in ConfDB as tailf:aes-cfb-128-encrypted-string leafs I can use the _ncs.decrypt() function, but I couldn't see an equivalent _ncs.encrypt() function in the docs. Is there a way to encrypt a string directly within python MAAPI to pass to a tailf:aes-cfb-128-encrypted-string leaf, or do we have to use a separate python crypto module to encrypt the string and then send it to the tailf:aes-cfb-128-encrypted-string leaf?
Solved! Go to Solution.
- Labels:
-
Technical product information
Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-31-2020 08:46 AM
I realized that another workaround could be to use a small template just for setting the password.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-30-2020 06:32 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-30-2020 09:45 AM
It appears to work if I run it through a maapi script, but not from directly inside the cb_create method of the python service. The following maapi script works:
import random import string import ncs from ncs import _ncs with ncs.maapi.Maapi() as m: with ncs.maapi.Session(m, 'admin', 'python'): with m.start_write_trans() as t: root = ncs.maagic.get_root(t) letters_and_digits = string.ascii_letters + string.digits aes_pass = ''.join((random.choice(letters_and_digits) for i in range(8))) root.wxc_vpn_snmp.wxc_vpn_customer.create('maapi') root.wxc_vpn_snmp.wxc_vpn_customer['maapi'].snmp_aes = aes_pass t.apply()
But the following code inside the cb_create method of the service gives me the bad type error:
if not root.wxc_vpn_snmp.wxc_vpn_customer[vrf_name].snmp_aes: letters_and_digits = string.ascii_letters + string.digits aes_pass = ''.join((random.choice(letters_and_digits) for i in range(8))) root.wxc_vpn_snmp.wxc_vpn_customer[vrf_name].snmp_aes = aes_pass
Any idea why this does not work?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-30-2020 09:57 AM
It could be a python2 vs python3 difference if the external script is run with python2. Python3 has a tendency to create Iterator-objects instead of collapsing them immediately which can cause trouble. You can try using str() and/or list() to coerce things to the correct type.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-31-2020 02:24 AM
I was running the maapi script through python3, and I am using python3 for NSO, so I don't think that can be the issue. I added some extra logging statements in the service and it definitely looks like the aes_pass var is being generated correctly as a string type. Below is the updated code:
if not root.wxc_vpn_snmp.wxc_vpn_customer[vrf_name].snmp_aes: letters_and_digits = string.ascii_letters + string.digits aes_pass = str(''.join((random.choice(letters_and_digits) for i in range(8)))) self.log.info('AES pass ', aes_pass, ', type ', type(aes_pass)) encoded_pass = '$0$' + aes_pass self.log.info('encoded pass ', encoded_pass, ', type ', type(encoded_pass)) root.wxc_vpn_snmp.wxc_vpn_customer[vrf_name].snmp_aes = encoded_pass
This results in the following log messaging when attempting a commit dry-run:
<INFO> 31-Jul-2020::04:17:41.712 wxc-vpn-customer MainThread: - Python 3.6.6 (default, Jan 26 2019, 16:53:05) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
<INFO> 31-Jul-2020::04:17:41.715 wxc-vpn-customer MainThread: - Starting...
<INFO> 31-Jul-2020::04:17:41.716 wxc-vpn-customer MainThread: - Started
<INFO> 31-Jul-2020::04:17:45.336 wxc-vpn-customer ComponentThread:main: - Main RUNNING
<INFO> 31-Jul-2020::04:17:59.960 wxc-vpn-customer ncs-dp-28246-wxc-vpn-customer:main-1-th-1192342: - Service create(service=/ncs:services/wxc-vpn-customer:wxc-vpn-customer{partner1 cust10})
<INFO> 31-Jul-2020::04:17:59.962 wxc-vpn-customer ncs-dp-28246-wxc-vpn-customer:main-1-th-1192342: - AES pass zS71qF3f, type <class 'str'>
<INFO> 31-Jul-2020::04:17:59.962 wxc-vpn-customer ncs-dp-28246-wxc-vpn-customer:main-1-th-1192342: - encoded pass $0$zS71qF3f, type <class 'str'>
<ERROR> 31-Jul-2020::04:17:59.963 wxc-vpn-customer ncs-dp-28246-wxc-vpn-customer:main-1-th-1192342: - item has a bad/wrong type (5): <<"$0$zS71qF3f">> is not a valid value.
<ERROR> 31-Jul-2020::04:17:59.964 wxc-vpn-customer ncs-dp-28246-wxc-vpn-customer:main-1-th-1192342: - Traceback (most recent call last):
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/application.py", line 399, in wrapper
pl = fn(self, tctx, root, service, proplist)
File "/home/tcragg/ncs52-run/state/packages-in-use/1/wxc-vpn-customer/python/wxc_vpn_customer/main.py", line 36, in cb_create
root.wxc_vpn_snmp.wxc_vpn_customer[vrf_name].snmp_aes = encoded_pass
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/maagic.py", line 483, in __setattr__
child.set_value(value)
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/maagic.py", line 956, in set_value
self._backend._set_elem(value, self._path)
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/maagic.py", line 124, in _set_elem
self.set_elem(value, path)
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/maapi.py", line 1202, in proxy
return real(self2.maapi, self2.th, *args, **kwargs)
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/tm.py", line 12, in wrapper
return fn(*args, **kwargs)
File "/home/tcragg/nso-5.2.3.3/src/ncs/pyapi/ncs/maapi.py", line 667, in shared_set_elem
_tm.maapi.shared_set_elem(self.msock, th, value, flags, path)
_ncs.error.Error: item has a bad/wrong type (5): <<"$0$zS71qF3f">> is not a valid value.
From the log messages, it looks like it is just refusing to accept a string value for this leaf.
I am running NSO 5.2.3.3 if that makes a difference.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-31-2020 08:03 AM
Hello,
This seems to be a limitation in maagic, currently.
It seems if you want to use maagic to set the value of an encrypted leaf (in a service callback), you will have to provide the 'already encrypted value' (ie., something that starts with $8$, in this case).
It works outside a service. You can also use plain maapi, and do maapi.shared_set_elem() inside the service callback. You can do something like
m = maapi.Maapi() th = m.attach(tctx) th.shared_set_elem('dummypass', '<path_to_encrypted_leaf>')
where 'tctx' is the transaction context you receive as a parameter to your service callback.
It just doesn't work in maagic, as of now.
Please create a support request, so that this can be fixed.
Thanks,
Ram

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-31-2020 08:46 AM
I realized that another workaround could be to use a small template just for setting the password.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-03-2020 05:45 AM
Separating the credentials into an XML template appears to allow me to pass the unencrypted credentials correctly, and is also a simpler approach than messing around with directly accessing MAAPI from inside the cb_create() method, so I will use this approach if I need to pass plain text to an encrypted leaf going forward.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-31-2020 10:09 AM
Thanks Ram.
I am not very familiar with the shared_set_elem command. What format does it expect the path to the element to be in? I assumed it would just be XPATH, but when I try "th.shared_set_elem(aes_pass, "/wxc-vpn-snmp/wxc-vpn-customer[vrf_name='maapi']/snmp-aes")", it gives me a bad path error. This should be a valid XPATH as it is pointing to an existing list entry:
admin_tcragg@ncs# show running-config wxc-vpn-snmp | display xpath /wxc-vpn-snmp/wxc-vpn-customer[vrf_name='maapi']/snmp-aes $8$DMo1By0HjgSiPRbz3FbBiuLJNe3aN2r5HjKNSutsk+o=

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-31-2020 10:13 AM
