Closed ggiesen closed 11 months ago
I have managed to get a little further by replacing this:
With this:
if self.optional_args.get('transport', 'http') == 'https' or self.optional_args.get('netbox_default_ssl_params', False):
ctx = ssl.create_default_context()
try:
IPAddress(self.hostname)
# IPAdresses cannot check hostname
ctx.check_hostname = False
except AddrFormatError:
# if hostname is not IP, we use check_hostname variable
ctx.check_hostname = self.optional_args.get('check_hostname', True)
if not self.optional_args.get('use_ssl_cert', True):
# Cannot use check_hostname with no certificate
ctx.check_hostname = False
# Disable certificate checking
ctx.set_ciphers('ADH:@SECLEVEL=0')
self.optional_args['ssl_wrapper'] = ctx.wrap_socket
and modifying my proxy config to this:
proxy:
proxytype: napalm
driver: ros
host: 192.0.2.1
username: admin
passwd: Iecee3quoh1Aimoh
multiprocessing: False
optional_args:
transport: https
use_ssl_cert: False
And I see it log in successfully:
[DEBUG ] dummy proxy __virtual__() called...
[DEBUG ] The functions from module 'napalm' are being loaded by dir() on the loaded module
[INFO ] nxos proxy __virtual__() called...
[DEBUG ] rest_sample proxy __virtual__() called...
[INFO ] ssh_sample proxy __virtual__() called...
[DEBUG ] Setting up NAPALM connection
[DEBUG ] <--- '/login'
[DEBUG ] <--- '=name=admin'
[DEBUG ] <--- '=password=Iecee3quoh1Aimoh'
[DEBUG ] <--- EOS
[DEBUG ] ---> '!done'
[DEBUG ] ---> EOS
[DEBUG ] Grains refresh requested. Refreshing grains.
[DEBUG ] Reading configuration from /etc/salt/proxy
[DEBUG ] Including configuration from '/etc/salt/proxy.d/mikrominion/_schedule.conf'
[DEBUG ] Reading configuration from /etc/salt/proxy.d/mikrominion/_schedule.conf
[DEBUG ] Including configuration from '/etc/salt/proxy.d/mikrominion/mikrominion.conf'
[DEBUG ] Reading configuration from /etc/salt/proxy.d/mikrominion/mikrominion.conf
But then fails with an error of TypeError: cannot pickle 'SSLContext' object
:
Traceback (most recent call last):
File "/bin/salt-call", line 11, in <module>
sys.exit(salt_call())
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/scripts.py", line 444, in salt_call
client.run()
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/cli/call.py", line 40, in run
caller = salt.cli.caller.Caller.factory(self.config)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/cli/caller.py", line 42, in factory
return ZeroMQCaller(opts, **kwargs)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/cli/caller.py", line 303, in __init__
super().__init__(opts)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/cli/caller.py", line 61, in __init__
self.minion = salt.minion.SProxyMinion(opts)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/minion.py", line 929, in __init__
self.gen_modules(initial_load=True, context=context)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/minion.py", line 3983, in gen_modules
self.opts["grains"] = salt.loader.grains(self.opts, proxy=self.proxy)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/__init__.py", line 1106, in grains
funcs = grain_funcs(
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/__init__.py", line 967, in grain_funcs
_utils = utils(opts, proxy=proxy)
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/__init__.py", line 534, in utils
return LazyLoader(
File "/opt/saltstack/salt/lib/python3.10/site-packages/salt/loader/lazy.py", line 249, in __init__
opts = copy.deepcopy(opts)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 146, in deepcopy
y = copier(x, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 231, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 146, in deepcopy
y = copier(x, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 231, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 146, in deepcopy
y = copier(x, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 231, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 146, in deepcopy
y = copier(x, memo)
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 238, in _deepcopy_method
return type(x)(x.__func__, deepcopy(x.__self__, memo))
File "/opt/saltstack/salt/lib/python3.10/copy.py", line 161, in deepcopy
rv = reductor(4)
TypeError: cannot pickle 'SSLContext' object
I realize the traceback is on the Salt side, but given that other drivers work fine, I'm curious if a) I'm doing something wrong or b) there is something nonstandard about this driver/other issues with this driver?
With some help from @ktbyers on Slack, I believe I've solved the issue. I replaced:
with the following:
self.ssl_wrapper = librouteros.DEFAULTS['ssl_wrapper']
if self.optional_args.get('transport', 'http') == 'https' or self.optional_args.get('netbox_default_ssl_params', False):
ctx = ssl.create_default_context()
try:
IPAddress(self.hostname)
# IPAdresses cannot check hostname
ctx.check_hostname = False
except AddrFormatError:
# if hostname is not IP, we use check_hostname variable
ctx.check_hostname = self.optional_args.get('check_hostname', True)
if not self.optional_args.get('use_ssl_cert', True):
# Cannot use check_hostname with no certificate
ctx.check_hostname = False
# Disable certificate checking
ctx.set_ciphers('ADH:@SECLEVEL=0')
self.optional_args['transport'] = 'https'
self.ssl_wrapper = ctx.wrap_socket
else:
self.optional_args['transport'] = 'http'
self.port = self.optional_args.get('port', 8729 if self.optional_args['transport'] == 'https' else 8728)
I don't see a reason the SSLContext needs to be passed through optional_args
via ssl_wapper
(resulting in the error when it's trying to be serialized by pickle), but perhaps @luqasz or @sHorst can advise?
Docs state it clearly why ssl context is used. HTTP / HTTPS is not supported by librouteros nor napalm-ros driver.
I apologize if I was unclear. The question is not why SSLContext is used, but why the object needs to be passed through optional_args instead of just having the driver create it (like it does when the netbox_default_ssl_params option is used).
Is there any reason it needs to be able to be passed through optional_args (rendering the driver unusable with Salt)? If I submit a PR similar to the code above, would it be accepted?
I've added ssl support into librouteros some time ago. Later I've added it to napalm due to requests / PRs from netbox users. Then problems started since some users want X, some Y and others Z. I didn't refactor it in order not to break what is already running. That being said I want to refactor all ssl code in napalm ros driver to give reasonable defaults and options.
I am open to discussion / PRs.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Description of Issue/Question
I'm trying to connect to a Mikrotik RBM33G from Salt using the napalm proxy minion, using TLS with no certificate. Looking through the code, unless I'm misreading (and admit that's fully possible as I don't follow it completely), the only way I could find to explicitly enable TLS is to set
netbox_default_ssl_params = True
.I have my proxy minion config as such:
When I try to issue a command, I get:
According to the librouteros docs, it looks like:
needs to be passed to the context, but I don't think there's any way to do that since I can't create the context from Salt. Am I wrong on this, and if so, is there any way to specifically add support certificate-less SSL via optional_args?
Setup
napalm-ros version
(Paste verbatim output from
pip freeze | grep napalm-ros
between quotes below)ROS version
(Paste verbatim output from
/system package print
between quotes below)librouteros version
(Paste verbatim output from
pip freeze | grep librouteros
between quotes below)python version
(paste output of python --version)
Steps to Reproduce the Issue
Error Traceback
(Paste the complete traceback of the exception between quotes below)