cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
183
Views
0
Helpful
7
Replies

PyATS fails to connect to APIC using rest.connector.Rest

Afternoon everyone, 

I'm trying to connect to an APIC using PyATS and the rest.connector.Rest method, but no matter what, I get authentication failures. Here is my testbed file:

devices:
  apic:
      os: apic
      type: apic
      custom:
        abstraction:
          order: [os]
      connections:
        rest:
          class: rest.connector.Rest
          protocol: http
          port: 443
          ip: 10.10.10.10
          verify: False
          username: "apic:Tacacs\\my.user.account"
          password: "my_password"

Here's the output from the pyats shell:


>>> testbed = load('aci_tb.yml')
-------------------------------------------------------------------------------            
>>> testbed.devices['apic'].connect(alias='rest', via='rest')
Connecting to 'apic' with alias 'rest'
<Response [401]>
{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"TACACS+ Server Authentication DENIED"}}}]}
Request to apic failed. Waiting 10 seconds before retrying

Traceback (most recent call last):
  File "/.robotFramework/lib64/python3.11/site-packages/rest/connector/libs/apic/implementation.py", line 144, in connect
    raise RequestException("Connection to '{ip}' has returned the "
requests.exceptions.RequestException: Connection to '10.10.10.10' has returned the following code '401', instead of the expected status code '200'

Here is the session log in the APIC showing the failure:

General
Description
From-10.10.10.20-client-type-REST-Failure
Settings
Affected
uni/userext
cause
unknown
clientTag
-
code
generic
Created
2024-04-22T17:49:09.915+00:00
ID
8590532284
Action
special
Session ID
-
severity
info
System Id
1
Trigger
login, session
txId
0
User
remoteuser-my_user

I have no issues connecting using the API with postman or ansible. 

I'm not sure if this is an issue with the domain in the testbed file, but I've tried a few different configurations, each with the same luck. 

 

Thanks!

7 Replies 7

No expert here, based on what you share above, PyATS might be interpreting the backslash (\) in the username format ("apic:Tacacs\my.user.account") as an escape sequence. This could lead to an unexpected username being sent to the APIC during authentication.

Hope this helps.

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Thanks for the reply @bigevilbeard . 

I updated the testbed like this:

devices:
  apic:
    os: apic
    type: apic
    custom:
      abstraction:
        order: [os]
    connections:
      rest:
        class: rest.connector.Rest
        protocol: http
        port: 443
        ip: 10.10.10.10
        verify: False
        credentials:
          rest:
            username: 'apic:Tacacs\my.user.account'
            password: "mypass"

I think the second '\' is to escape the domain backslash. If I remove it, I get an error:

YAML Lint Messages
------------------
  3:7       warning  wrong indentation: expected 4 but found 6  (indentation)
  17:41     error    syntax error: found unknown escape character 'm' (syntax)

Errors
------
 - while scanning a double-quoted scalar
  in "/aci_tb.yml", line 17, column 25
found unknown escape character 'm'
  in "/aci_tb.yml", line 17, column 41

I do think you're on to something with how its passing the username/password though, I just cant figure out the correct format. 

Try this way... might be the way...

username: "apic:Tacacs\\\\my.user.account"

 

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Thanks! With 2 or 3 extra backslashes, I just get an invalid character error. Looking at my user account in the MO browser, I can see that there's actually no loginDomain.

{
    "totalCount": "1",
    "imdata": [
        {
            "aaaRemoteUser": {
                "attributes": {
                    "annotation": "",
                    "childAction": "deleteNonPresent",
                    "ciscoAvPair": "shell:domains=all/admin/",
                    "descr": "",
                    "dn": "uni/userext/remoteuser-my.user.account",
                    "extMngdBy": "",
                    "lcOwn": "local",
                    "loginDomain": "",
                    "loginTime": "2024-04-23T14:29:32.000+00:00",
                    "modTs": "2024-04-23T14:33:55.652+00:00",
                    "name": "my.user.account",
                    "nameAlias": "",
                    "ownerKey": "",
                    "ownerTag": "",
                    "sequenceNumber": "57",
                    "stateCode": "",
                    "status": "",
                    "uid": "0",
                    "unixUserId": "23645",
                    "userdom": "all"
                }
            }
        }
    ]
}

 If I try to pass the username with no domain, I still get a 401 error. 

<Response [401]>
{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"TACACS+ Server Authentication DENIED"}}}]}
Request to apic failed. Waiting 10 seconds before retrying

Ok, so the fact that your user account in the MO browser shows no loginDomain clarifies why your username format with domain is not working here. Try in the PyATS testbed file, set the verify option to False under the rest connection for the apic device. That disables certificate verification, which might be enforcing domain checks maybe?

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Thanks for the reply, verify: False results in the same 401 error. 

Just as a heads up, I've also opened an issue on the CiscoTestAutomation repo here.  

Cool, the only thing i thought of was not including the domain in the username string and setting this up as seperate field to specify the domain in the tesbed file.... But guessing here, as i have nothing to test on.

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io