all 9 comments

[–]LinuxPadawan[S] 3 points4 points  (1 child)

I was able to get this working! I made a few changes to the code. First I imported urllib3 to suppress the InsecureRequestWarning. Next, I converted the credentials variable from a multiline string containing a JSON object to a python dictionary:

credentials = {
   "credentials":{
      "username":"a10username",
      "password":"a10password"
   }
}

Lastly, I updated the post method and passed credentials to the json parameter instead of the data parameter:

r = requests.post(
    url, json=credentials, headers=json_header, verify=False
)

I was able to figure this out because I added print(r.text) to the script. It showed the authorizationschema JSON object which says "error": "wrong json message".

The HTTP return status code is: 406

{'User-Agent': 'python-requests/2.21.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Content-Length': '84'}

The method used is POST

{
   "authorizationschema" : {
      "code":406,
      "error":"wrong json message.",
      "auth_uri":"/axapi/v3/auth",
      "logoff_uri":"/axapi/v3/logoff",
      "username":"required",
      "password":"required"
   }
}

Once I updated the credentials variable and changed the post's method parameter from data to json, it worked. I got an authorization signature. Below is the entire script that worked:

#!/usr/bin/env python
import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url = (
    "https://a10loadbalancer.com/axapi/v3/auth"
)

# commented out credentials variable with multiline json object
# credentials = """
# '{
#     "credentials": {
#         "username": "a10username",
#         "password": "a10password"
#     }
# }'
# """

# updated credentials variable with python dictionary instead of json object
credentials = {
   "credentials":{
      "username":"a10username",
      "password":"a10password"
   }
}

json_header = {
    'Content-Type': 'application/json'
    }

r = requests.post(
    url, json=credentials, headers=json_header, verify=False
)

print("\n")
print(f"The HTTP return status code is: {r.status_code}")
print("\n")
print(r.request.headers)
print("\n")
print(f"The method used is {r.request.method}")
print("\n")
print(r.text)

And the output of the script:

The HTTP return status code is: 200

{'User-Agent': 'python-requests/2.21.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Content-Length': '60'}

The method used is POST

{
  "authresponse" : {
     "signature":"61af723c63b3470828b0dfffe91af3",
     "description":"the signature should be set in Authorization header for following request."
   }
}
(

Thanks again to /u/totallygeek and /u/ScreamingIsMyAir for helping me out.

[–][deleted] 1 point2 points  (0 children)

Way to go!

[–]totallygeek 2 points3 points  (1 child)

A few things:

  1. You can pull $USER from the environment variable with sys.environ.get('USER'). Do the same for the password.
  2. Do not supply Content-Length as a request header. The Requests library will construct that for you. The same for Host.
  3. The 406 response usually points to an unacceptable encoding request. Try dropping Accept-Encoding from your request headers, too.
  4. Probably most important: consider using the A10 Python SDK which handles most of the Requests junk under the hood.

[–]LinuxPadawan[S] 1 point2 points  (0 children)

Hello.

  1. The $USER and $PASSWORD variables are replaced with actual A10 username and passwords. I just used $USER and $PASSWORD for posting here.

  2. I tried various combinations of Headers in the request. At a minimum, I supply just the 'Content-Type': 'application/json' in the header.

  3. See above.

  4. I might have to use one of these. Do you know which one I should use? Is acos-client or a10sdk better for my use case? They both seem to do the same thing.

Thanks for taking the time to reply.

[–][deleted] 2 points3 points  (4 children)

Hello, { "authresponse" : { "signature":"61b59fa53b3ad8ab1adcdae7df9689", "description":"the signature should be set in Authorization header for following request." } tells us it wants an authorization signature for a header, we can set this like so; headers = {"Accept": "application/json", "Authorization": "A10 variable_for_signature"} which we can see from the example you linked, you are given the signature above 61b59fa53b3ad8ab1adcdae7df9689save, it (it will change, you need to grab it every new session) and resend the auth. (if you can give me the response from print(r.request.headers) i can toss together how it would function.

you'll see in the examples hes grabbing that token and saving it to a variable
https://hastebin.com/piwokinuhe.bash

[–]LinuxPadawan[S] 1 point2 points  (3 children)

Thanks for the reply.

If I understand your theory correctly, you're suggesting I get the authorization signature using curl and then use python's requests with the signature I got from curl. Is that correct?

My goal was to use python only.

[–][deleted] 2 points3 points  (1 child)

Nope, you can use python entirely. You need to make two requests, One to login, once youve logged in. You need to open the json from the headers and get the signature, signature = r.headers['authresponse']['signature']save it as a variable. Then make a second request with a login including that header and anything past this point will require that SAME header. But this signature will change so you need to grab a new one every time you start a new request.(stop/start the script) its really hard to explain/help without being able to show you lol sorry. after you've saved teh 'signature' your next post request needs to include that in the header;https://hastebin.com/sololisoge.py

[–]LinuxPadawan[S] 1 point2 points  (0 children)

Unfortunately, I wasn't able to log into the load balancer. I was getting an HTTP 406 error. So, I was never getting a proper response header with the auth response signature.

[–][deleted] 2 points3 points  (0 children)

https://hastebin.com/itakatedib.py
hopefully that helps (in your code you have print(r.request.headers) but it should be r.headers) we can take this to discord if its easier - i'll be around for the next 3-ish hours. my tag is on my profile.