CiscoISE/ciscoisesdk

Delete endpoint: CSRF nonce validation failed [403]

Closed this issue · 9 comments

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version? => ciscoisesdk==1.4.2

Describe the bug
When trying to delete an existing endpoint, the API throws an ciscoisesdk.exceptions.ApiError with the following message:

2022-02-21T14:47:03: %AETEST-ERROR: ciscoisesdk.exceptions.ApiError: [403] - CSRF nonce validation failed<!DOCTYPE html>
2022-02-21T14:47:03: %AETEST-ERROR: <html lang="en">
2022-02-21T14:47:03: %AETEST-ERROR:     <head>
2022-02-21T14:47:03: %AETEST-ERROR:         
2022-02-21T14:47:03: %AETEST-ERROR:     </head>
2022-02-21T14:47:03: %AETEST-ERROR:     <body>
2022-02-21T14:47:03: %AETEST-ERROR:         <div class="container">
2022-02-21T14:47:03: %AETEST-ERROR:             <h1>[ 403 ] </h1>
2022-02-21T14:47:03: %AETEST-ERROR:             <p></p>
2022-02-21T14:47:03: %AETEST-ERROR:         <p></p>
2022-02-21T14:47:03: %AETEST-ERROR:         </div>
2022-02-21T14:47:03: %AETEST-ERROR:     </body>
2022-02-21T14:47:03: %AETEST-ERROR: </html>

The code is quite simple (dummy data)

from ciscoisesdk import IdentityServicesEngineAPI
from ciscoisesdk.exceptions import ApiError
api = IdentityServicesEngineAPI(
            username=ers_rw_user,
            password=ers_rw_pw,
            uses_api_gateway=True,
            base_url="https://myise.example.org",
            version=3.1.1,
            verify=False)

delEp = api.endpoint.delete_endpoint_by_id(id = "5103b400-931b-11ec-ab1b-ae32d00e1b2c")

When CSRF checking is disabled in the ISE settings, the delete operation works as expected

Expected behavior
It should be possible to delete an endpoint by id with enable CSRF validation

Environment (please complete the following information):

  • ISE version and patch: 3.1.0.518 Patch 1
  • Python version: 3.6.8
  • SDK version: 1.4.2
  • OS version: CentOS Stream 8 (x86_64)

Hi, @netgab. Thanks for pointing this out to us. I will make the necessary updates and notify you when done.

While on work on a more general approach, you can add the value in headers.

delEp = api.endpoint.delete_endpoint_by_id(id="5103b400-931b-11ec-ab1b-ae32d00e1b2c",
                                           headers={"X-CSRF-TOKEN": "<your value>"})

Hi @wastorga
does it work? Because in ISE it's not enough to set the X-CSRF-TOKEN header.
When doing it via curl the session cookie needs to be saved in the GET request (the request which fetched the CSRF token) and this session cookie must be sent in the write operation ("PUT", "POST", "DELETE")

It works but with a little work.

r1 = api.endpoint.get_version(headers={"X-CSRF-TOKEN": "fetch"})
r2 = api.endpoint.delete_by_id("be46f4f0-932f-11ec-aa4c-8e0da8a23ad8",
                               headers={"X-CSRF-TOKEN": r1.headers["X-CSRF-Token"]})

We use a requests' session which stores the cookie.

Workaround works like a charm. Thank you!

I added a way for the SDK to manage it automatically for you. [CSRF Token Check](https://ciscoisesdk.readthedocs.io/en/develop/api/quickstart.html#csrf-token-check)
I will publish the new version soon.

@netgab
The ciscoisesdk v1.5.0 is up. Feel free to test it and close or comment if necessary.

Works perfectly with uses_csrf_token. However your workaround using the custom headers was working like a charm was well :)
Thank you for the very fast implementation!