stmcginnis/gofish

X-Auth-Token need CSRFToken

admover opened this issue · 16 comments

Hi.
When I use it for Inspur, it's return "panic: 401: { "cc": 7, "error": "Invalid Authentication" }", please help me!

Postman:
-Create session:https://192.168.1.1/redfish/v1/SessionService/Sessions
-Response:
{ "default_passwd": 0, "ResidueDay": 255, "ok": 0, "privilege": 4, "extendedpriv": 259, "racsession_id": 50, "remote_addr": "192.168.1.2", "server_name": "192.168.1.1", "server_addr": "192.168.1.1", "HTTPSEnabled": 1, "CSRFToken": "Ydom4LCh", "Id": "509103346d39ead083Q3wDT6xjK8UqYdom4LCh" }
X-Auth-Token: 509103346d39ead083Q3wDT6xjK8UqYdom4LCh
Location: /redfish/v1/SessionService/Sessions/509103346d39ead083Q3wDT6xjK8Uq

Hey @admover - I've never run against an Inspur device. Is it possible you need to enable different authentication methods? Looks like maybe it doesn't have the default auth enabled?

Thank you, I will try.

It work when i use it in Postman.

======================= Inspur=====================
Response header:image
Response body:image
Get sessions:image

=======================HP=======================

Response header:image
Response body:image
Get sessions:image

I'm still trying to parse out what is relevant above and what it is you are looking for. Looks like in both cases the responses return a code of 201. Both headers contain the expected Location and X-Auth-Token.

It does appear the Inspur host has an invalid (does not follow the Redfish spec) response body, but that should not be an issue in our case since we do not need to parse that session object at this point.

JSON response body. Contains the full representation of the new Session resource.

You mention needing a CSRFToken, so I'm assuming you're saying that Inspur needs this token included in headers for subsequent calls? Again, that is non-standard, but at a minimum they are not following the Redfish spec with the response they are sending, so that would need to change with the vendors implementation to return that value as a header. We could probably add a check for its presence in https://github.com/stmcginnis/gofish/blob/main/redfish/session.go#L94-L96 and include it when making authenticated calls.

sessions, err := service.Sessions()
if err != nil {
    panic(err)
}

I tested it in Postman and when X-Auth-Token is not verified, it returns { "cc": 7, "error": "Invalid Authentication" },
How can I get the current X-Auth-Token when calling sessions, err := service.Sessions()?

You would not have access to it from service.Session(). You really shouldn't need it either as it's an internal communication detail with the server.

It looks like you need to get the CSRFToken returned so that can be sent as part of the headers. I'm assuming here, since I don't have access to an Inspur system and am not sure what they actually are expecting. But since they do not follow the Redfish specification for session creation, I think it would be up to the vendor to fix their implementation so we can extract that from the response headers and use it for subsequent calls.

ok, thank you again.

If I open the redfish api for you, can you check why?

Thanks @admover. If I had access I can confirm what you've already posted above.

Can you tell me your public IP? I need to configure the firewall access list.

Sorry, I don't have a public static IP address.

Okay, please tell me your email and I will send you the authentication information.

I have confirmed I get the same response you were seeing. Rather than sending a valid Session object back from the login, the Inpur devices is returning a non-standard JSON struct:

{ "default_passwd": 0, "ResidueDay": 255, "ok": 0, "privilege": 4, "extendedpriv": 256, "racsession_id": 6, "remote_addr": "72.50.207.44", "server_name": "116.239.7.117", "server_addr": "192.168.30.85", "HTTPSEnabled": 1, "CSRFToken": "rykXBkIm", "Id": "ecd10d18c6066bf79bkAylQAxrxQl1rykXBkIm" }

And there is no CSRFToken in the response headers:

X-Xss-Protection : [1; mode=block]
Location : [/redfish/v1/SessionService/Sessions/ecd10d18c6066bf79bkAylQAxrxQl1]
X-Auth-Token : [ecd10d18c6066bf79bkAylQAxrxQl1rykXBkIm]
Content-Type : [application/json]
Set-Cookie : [QSESSIONID=ecd10d18c6066bf79bkAylQAxrxQl1; path=/; secure;HttpOnly]
Date : [Mon, 30 Aug 2021 17:43:35 GMT]
X-Content-Type-Options : [nosniff]
Strict-Transport-Security : [max-age=31536000; includeSubDomains]
Content-Security-Policy : [default-src 'none'; child-src 'self' 'unsafe-inline' 'unsafe-eval'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self' wss://*:*; img-src 'self' data:; frame-src 'self'; font-src 'self'; object-src 'self'; style-src 'self' 'unsafe-inline']
X-Frame-Options : [SAMEORIGIN]

So this confirms they are not following the Redfish spec. If the CSRFToken is needed to be passed along in subsequent calls, they would need to change that to be returned in the response headers. If that is done, gofish could be updated to look for that in the headers and store it to pass back in authenticated calls like what is done with things like X-Auth-Token.

If you have a support contract for this hardware, I would recommend opening a support ticket with Inspur and raising this as an issue. They are not following the Redfish specification, so they need to review the spec and correct their implementation.

For their reference, the session login is detailed in section 15.3.4.2 in the spec available here: https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.13.0.pdf

The response to the POST request to create a session shall include:
• X-Auth-Token header. Contains a session authentication token that the client can use in subsequent requests.
• Location header. Contains a hyperlink to the new Session resource.
• JSON response body. Contains the **full representation of the new Session resource**.

Going to close this issue as it is not something wrong in the gofish client. Feel free to reopen or file a new issue if Inspur is able to correct their implementation and we can take a look at adding custom CSRFToken handling, as long as it can be done in a way that will not cause issues with spec-conforming implementations.

Thank you for your help.

@stmcginnis
req.Header.Set("Cookie", fmt.Sprintf("sessionKey=%s", c.auth.Token))
I found the problem
If the authentication is passed, the program will add a cookie as "sessionKey= XXXXXXXXXXXXXXXXXXXXXX"
But the cookie returned by the device is "QSESSIONID=XXXXXXXXXXXXXXXXXXXXXX"
I commented out this line and the program is running.
But it return other panic when use service.Sessions(), i'm sad.
panic: failed to retrieve some items: [{"link":"3a9808670d509ccaf91Sh62LqBxSIt","error":"invalid character '\\x1f' looking for beginning of value"}]