Join the Conversation

To sign in, use your existing MySonicWall account. To create a free MySonicWall account click "Register".

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.

Category: Developer Hub
Reply

Best Answer

Answers

  • Adding @Jaime and @skesarwa to this thread as they are experts on this.

    Thanks!

    Shipra Sahu

    Technical Support Advisor, Premier Services

  • brunogabrielbrunogabriel Newbie ✭

    Following this thread.

  • daniel_liljadaniel_lilja Enthusiast ✭✭
    edited June 2020

    Hi @hbonath , try set the following headers:

    headers={

    'Accept-Encoding': '*/*',

    'Accept': '*/*',

    },


    I actually think this a bug, but this has been working for us.

  • JaimeJaime SonicWall Employee

    Hi,

    Please give this a try and let me know if the response is any different:

    from collections import OrderedDict
    
    headers = OrderedDict([
    	('Accept', 'application/json'),
    	('Content-Type', 'application/json'),
    	('Accept-Encoding', 'application/json'),
    	('charset', 'UTF-8')])
    

    Thanks.

    Jaime

  • hbonathhbonath Newbie ✭
    edited June 2020

    @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:

    import requests
    import urllib3
    from collections import OrderedDict
    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 = OrderedDict([
                ('Accept', 'application/json'),
                ('Content-Type', 'application/json'),
                ('Accept-Encoding', 'application/json'),
                ('Charset', 'UTF-8')])
    
        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()
                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()
                return response
    
    
    def main():
        s = sonicapi('192.168.168.168', 443, 'admin', 'password')
        print(s.auth())
        print(s.getIPv4AddressObjects())
    
    
    if __name__ == "__main__":
        main()
    
    
    
    


  • This is great! I'll have to try this out. Thanks for the collaboration!

    @micah - SonicWall's Self-Service Sr. Manager

  • hbonathhbonath Newbie ✭

    I've created a new repo to keep this at where this can be eventually built upon to be imported into other projects.


Sign In or Register to comment.