pythoncurlpython-requestsaruba

Logging in to Aruba's NBAPI for Mobility Master with requests failing


I am using requests to call to Aruba's NBAPI for mobility master. Their documentation is scarce with Python examples. The API requires an initial auth to get a UID which needs to be referenced in each GET request. I cannot get the login to work within Python.

I'm using a GET request which may be part of the issue but it's my understanding of the curl example provided by Aruba the default GET method is being used. Please note I'm also not verifying the SSL cert as my end goal is zero touch provisioning.

Here is the curl command they offer to auth

curl --insecure -c "aruba-cookie-jar" -d "username=username&password=password" https://<url-here>:4343/v1/api/login

command output:

{"_global_result": {"status":"0", "status_str": "You've logged in successfully.", "UIDARUBA":"<key output here>"}}

I tried to convert this into python using 'requests' as shown below

import requests

session = requests.Session()
session.verify = False
r = session.get('https://<url-here>:4343/v1/api/login', auth=('username', 'password'))

I get the below when checking response (ipython)

In [6]: r.status_code
Out[6]: 401
In [7]: print(r.text)
{"_global_result": {"status":"1", "status_str": "Unauthorized request, authentication failed"}}

What am I doing wrong with this request? When using the POST method in Python results in the same output. I am thinking the auth method being used in my Python example is not correct.


Solution

  • You are not making the same request. The -d switch for curl sends POST data, not an authorization header. From the curl documentation:

    -d, --data <data>

    (HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded.

    You are using a GET request, not POST. Send the username and password in the data argument, you can use a dictionary here to have requests handle encoding it to a application/x-www-form-urlencoded formatted request body:

    session = requests.Session()
    session.verify = False
    login_info = {'username': 'username', 'password': 'password'}
    r = session.post('https://<url-here>:4343/v1/api/login', data=login_info)
    

    In general, API documentation that uses curl command-line examples count on a minimal familiarity with that tool, it is always worth reading the curl manpage to understand what the switches do, as well as have a minimal understanding of HTTP headers and the likes.

    When in doubt, use both curl and requests to send your request to the httpbin.org test site, and compare the results. Here, using the /anything endpoint with curl gives:

    $ curl --insecure -c "aruba-cookie-jar" -d "username=username&password=password" https://httpbin.org/anything
    {
      "args": {},
      "data": "",
      "files": {},
      "form": {
        "password": "password",
        "username": "username"
      },
      "headers": {
        "Accept": "*/*",
        "Content-Length": "35",
        "Content-Type": "application/x-www-form-urlencoded",
        "Host": "httpbin.org",
        "User-Agent": "curl/7.54.0"
      },
      "json": null,
      "method": "POST",
      "origin": "...",
      "url": "https://httpbin.org/anything"
    }
    

    while your request code outputs:

    >>> import requests
    >>> session.verify = False
    >>> r = session.get('https://httpbin.org/anything', auth=('username', 'password'))
    /.../lib/python3.8/site-packages/urllib3/connectionpool.py:842: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
      warnings.warn((
    >>> print(r.text)
    {
      "args": {},
      "data": "",
      "files": {},
      "form": {},
      "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=",
        "Host": "httpbin.org",
        "User-Agent": "python-requests/2.21.0"
      },
      "json": null,
      "method": "GET",
      "origin": "...",
      "url": "https://httpbin.org/anything"
    }
    

    which should hopefully make it clearer what the differences where here.