Python3 connection to SonicOS API
Does anyone have any working Python3 code that can successfully connect to the SonicOS API?
I have made several attempts using both the "requests" and "urllib" Python modules, however in all cases, the SonicWALL API returns a "406 Not Acceptable" response.
My Code:
import requests import urllib3 urllib3.disable_warnings() class sonicapi: def __init__(self, hostname, port, username, password): self.baseurl = 'https://{0}:{1}/api/sonicos/'.format(hostname, str(port)) self.authinfo = (username, password) self.headers = { 'Connection': None, 'Accept-Encoding': None, 'Content-Length': None, } def auth(self): controller = 'auth' url = self.baseurl + controller r = requests.post(url, auth=self.authinfo, headers=self.headers, verify=False) if r.status_code != 200: return r.status_code else: response = r.json().pop('data') return response def getIPv4AddressObjects(self): controller = 'address-objects/ipv4' url = self.baseurl + controller r = requests.get(url, auth=self.authinfo, headers=self.headers, verify=False) if r.status_code != 200: return r.status_code else: response = r.json().pop('data') return response def main(): s = sonicapi('192.168.168.168', 4343, 'admin', 'password') s.auth() s.getIPv4AddressObjects() if __name__ == "__main__": main()
The above code returns: 406 Not Acceptable
If I use curl from within bash, it seemingly works fine:
curl -k -i -u admin:password -X POST
https://192.168.168.168:4343/api/sonicos/auth
HTTP/1.1 200 Connection established HTTP/1.0 200 OK Server: SonicWALL Expires: -1 Cache-Control: no-cache Content-type: application/json; charset=UTF-8 X-Content-Type-Options: nosniff { "status": { "success": true, "info": [ { "level": "info", "code": "E_OK", "message": "Success." } ] } }
I have set up mitmproxy and tested both curl and Python, the only difference is that Python is sending an implicit "Accept-Encoding: identity" header, which curl otherwise is not.
I have opened a case as well after spending about 6 hours on this, using different model SonicWALLs with different OS Versions, I have been on the #Python IRC channel, and have exhausted all resources - it seems crazy to me that the SonicOS API would not be RFC Compliant or or otherwise incompatible with Python3.
My Environment:
SonicWALL NSA6600: SonicOS Enhanced 6.5.4.5-53n
SonicWALL NSv200(KVM): SonicOS Enhanced 6.5.4.4-44v-21-757-3d1fff93
Python version 3.6.10, requests module version 2.18.4. Ubuntu 18.04
I have also tested with Python 3.8.2, requests 2.22.0 on Ubuntu 20.04 with the same results.
Best Answer
-
Jaime SonicWall Employee
In your class:
class sonicapi: def __init__(self, hostname, port, username, password): self.baseurl = 'https://{0}:{1}/api/sonicos/'.format(hostname, str(port)) self.authinfo = (username, password) self.headers = OrderedDict([ ('Accept', 'application/json'), ('Content-Type', 'application/json'), ('Accept-Encoding', 'application/json'), ('charset', 'UTF-8')])
7
Answers
Adding @Jaime and @skesarwa to this thread as they are experts on this.
Thanks!
Shipra Sahu
Technical Support Advisor, Premier Services
Following this thread.
Hi @hbonath , try set the following headers:
headers={
'Accept-Encoding': '*/*',
'Accept': '*/*',
},
I actually think this a bug, but this has been working for us.
Hi,
Please give this a try and let me know if the response is any different:
Thanks.
Jaime
@Jaime -
Thank you, that is exactly what needed to be in there, specifically the 'Accept-Encoding' and 'Accept' headers being set to 'application/json'
The code is now working, and I am able to successfully connect to all of the devices I have been testing with and pull a list of Address Objects.
Here's the updated functional script for future reference:
This is great! I'll have to try this out. Thanks for the collaboration!
@micah - SonicWall's Self-Service Sr. Manager
I've created a new repo to keep this at where this can be eventually built upon to be imported into other projects.