mirror of
https://github.com/nspcc-dev/neofs-http-gw.git
synced 2026-03-01 04:29:08 +00:00
HTTP headers vs. NeoFS attributes and associated logic #99
Labels
No labels
I1
I3
I4
S2
S3
S4
U2
U2
U3
U4
blocked
bug
config
documentation
enhancement
go
good first issue
help wanted
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nspcc-dev/neofs-http-gw#99
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @roman-khimov on GitHub (May 25, 2023).
Suppose you're trying to make a real send.fs.neo.org, not a fake one, but the one that really uses the underlying technologies. So you set up a container that looks like this:
It's sowewhat open for the basic ACL, but it's got an extended one as well that fixes it:
Basically, no one but the owner can do anything with it, an attempt to upload any object will fail miserably:
And that's what we want, because our mighty neofs-oauthz will issue proper token for us with a very simple constraint:
One can upload, but only if the uploaded object has an
Emailattribute of very specific kind (hash of the e-mail received via OAuth). All good. There is nspcc-dev/neofs-oauthz#29, but let's consider it to be fixed for the moment.The way send.fs.neo.org works is it uploads objects via HTTP gateway (that's why we're here!), so frontend initiates upload with
Notice
X-Attribute-EmailandAuthorization, that's exactly what HTTP gateway needs to get a bearer token and anEmailattribute for the object. But what we receive as a reply for this request is not a CID/OID pair, butHow could it happen? If we're to extract the bearer token and email hash from the browser and try going via CLI, that'd be like:
And it works just fine (thanks, NeoFS). But if we're to
It still doesn't work. Now let's remember that the setup is a little more complicated than that and in fact we've got an nginx in-between the HTTP gateway and the client. It does some
proxy_passfor requests with slight URL adjustments, cachesGETs, so it's useful there. But it passes the headers as well.If we're to try to push the same request to the gateway directly (right from the appropriate host):
It all suddenly works again! But it's not via the nginx. So nginx can be easily blamed for this, but in fact it's still a little more complicated than that. If you're to carefully look at
http-gwdebug logs you may notice that the gateway doesn't use any bearer token at all for the upsteam request, no wonder it's denied. But if we're to also trytcpdump -A -i lo port 8888to see what's going on on the wire there are expected headers there:So why can't HTTP gateway take the token and use it? The answer to that is this attempt:
Which suddenly doesn't work at all. And the only difference with the successful one is lowercased
authorizationheader.RFC 2616 says:
So one might argue that the header is OK, but there is something wrong with the l33t fasthttp server we're using. Yes and no, we set it up this way:
nspcc-dev/neofs-http-gw@8321181b29/app.go (L120)And this knob is documented as "Header names are passed as-is without normalization if this option is set" (hi, #125 also). Why do we have it then? Well, NeoFS (unlike HTTP) has case-sensitive attributes and gateway is documented to accept them from HTTP headers:
Obviously if you want
Ololoyou have to have this passed asOloloasololois a different attribute.Maybe nginx can be fixed to not change attributes? No, because it only cares about HTTP and it's absolutely compatible with the 1.1 specification while HTTP 2.0 is even more interesting:
Our http gateway is 1.1 only, but nginx obviously works with any HTTP version and does what's more appropriate for it to do (lowercases everything). And if we're to consider switching to HTTP 2.0 then the whole attribute scheme breaks completely as we'll never receive
Ololoand couldn't sendX-Attribute-Ololoin response as well (like we do now).What options do we have?
DisableHeaderNamesNormalizingback tofalse? This seems like an easy solution,emailbecomesEmailagain,Authorizationis alwaysAuthorizationirrespective of how it's encoded in the request, all good. Except that the example from the README withX-Attribute-FilePathbreaks immediately, it'll beFilepath, sorry.Authorizationspecially, iterate through all headers manually and do case-insensitive comparisons to find it? Yeah, but this may then also be required forfasthttp.HeaderDateand doesn't solve object attribute problem (we may switch toemailfor send.fs.neo.org, but in general the problem still remains).I tend to think we might do 2 as a quick fix, but this problem may eventually bite us in some other setting. Opinions are welcome.
@roman-khimov commented on GitHub (May 26, 2023):
X-NeoFS: AttrName valuemay be OK for 5, we've never supported spaces in attributes anyway.