stmcginnis / gofish

Gofish is a Golang client library for DMTF Redfish and SNIA Swordfish interaction.
BSD 3-Clause "New" or "Revised" License
211 stars 113 forks source link

X-Auth-Token need CSRFToken #157

Closed admover closed 3 years ago

admover commented 3 years ago

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

stmcginnis commented 3 years ago

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?

admover commented 3 years ago

Thank you, I will try.

admover commented 3 years ago

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

stmcginnis commented 3 years ago

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.

admover commented 3 years ago
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()?

stmcginnis commented 3 years ago

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.

admover commented 3 years ago

ok, thank you again.

admover commented 3 years ago

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

stmcginnis commented 3 years ago

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

admover commented 3 years ago

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

stmcginnis commented 3 years ago

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

admover commented 3 years ago

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

stmcginnis commented 3 years ago

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.

stmcginnis commented 3 years ago

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.

admover commented 3 years ago

Thank you for your help.

admover commented 3 years ago

@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"}]