-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
server/authorizer: Fix gzip payload handling. #6825
server/authorizer: Fix gzip payload handling. #6825
Conversation
✅ Deploy Preview for openpolicyagent ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
6805365
to
34889a4
Compare
I'm a bit surprised about the approach taken here 😅 I'd have expected us to change the ordering of handlers, since we’re setting up the authzHandler (via initRouters) before the compressHandler. One could argue that authz should happen before decompress (to avoid an attack vector, decompressing not-yet-authorized bodies), but if we end up decompressing in the authz handler anyways, that point is moot. 🤔 Am I missing something that makes this idea flawed? 😃 |
Ooooh that linked code (CompressHandler) only takes care of compressing the response, doesn't it? That's not what we need, of course. I guess the alternative approach taken that I had in mind would be to have some sort of middleware for both request payloads and response payloads. 💭 |
@srenatus, I do think you've got a valid point w.r.t. the gzipped not-authorized-yet message bodies. I like the idea of having a uniform bit of middleware for decompressing requests! I'll take a look at how hard that would be to implement, and will ping back in this thread with the results. |
If we can keep authentication -> compression -> authorization, so authentication will be first, then I think it's no problem at all. |
Gotcha! Authentication first should not be an issue-- it's authorization and decompression that have a fixed ordering relative to each other. |
I think we actually could do some validation on gzip payload reads, but the method I have in mind relies on low-level knowledge of the format, namely, that the 8-byte trailer at the end of any valid gzip-compressed blob includes the CRC, as well as the decompressed file size in bytes, modulo Here's a sketch of what a
Maybe I'm overthinking things? I do think this approach would both boost performance for gzipped requests, and (if my understanding of the Notes:
|
@srenatus I've added the some gzip + authz policy test cases, so that's no longer a blocker. The tests have some extra cruft in them to allow turning the authz policy parts on/off while I experiment with the |
On this branch, if I have no authz policy and run:
I get a
I get:
Given that I don't do authn/authz on the request, it's not surprising if the changes in this PR aren't exercised, but wouldn't we expect the latter request to succeed? |
@johanfylling I tried running that command with plain
⬇️
I wonder if it's a behavior difference or a bug in |
9ddebe2
to
3fd8c3f
Compare
@philipaconrad , you're correct: |
3fd8c3f
to
cb39173
Compare
In tests with a 1GB gzipped input to Other endpoints check the request context to see if the input was already parsed for them, but
N = 1024 * 1024
oneKBString = "A" * 1024
if __name__ == "__main__":
print('{"input":{')
for i in range(0, N):
print('"{}": "{}",'.format(i, oneKBString))
print('"{}": "{}"'.format(N, oneKBString))
print("}}") Example CLI (server): /usr/bin/time -v ./opa-pr run -s --authorization=basic authz.rego Example CLI (client): python3 geninput.py | gzip | curl -H "Content-Encoding: gzip" --data-binary @- http://127.0.0.1:8181/v1/data |
if err != nil { | ||
return nil, err | ||
} | ||
defer gzReader.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation potentially leaks the gzip.Reader
. In util/read_gzip_body.go
in this PR, I add back this utility function, but with corrected defer
behavior.
This PR fixes an issue where an OPA running authorization policies would be unable to handle gzipped request bodies. Example OPA CLI setup: opa run -s --authorization=basic Example request: echo -n '{}' | gzip | curl -H "Content-Encoding: gzip" --data-binary @- http://127.0.0.1:8181/v1/data This would result in unhelpful error messages, like: ```json { "code": "invalid_parameter", "message": "invalid character '\\x1f' looking for beginning of value" } ``` The cause was that the request body handling system in the `server/authorizer` package did not take gzipped payloads into account. The fix was to borrow the gzip request body handling function from `server/server.go`, to transparently decompress the body when needed. Fixes: open-policy-agent#6804 Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
da71251
to
0182db3
Compare
ℹ️ Here's the current state of things (for @johanfylling, @srenatus, and anyone else following along): The good news:
The bad news:
Unless there's any other comments/critiques/requests around this PR, I think it should be good-for-merge now. |
What changed in this PR?
This PR fixes an issue where an OPA running authorization policies would be unable to handle gzipped request bodies.
Example OPA CLI setup:
Example request:
This would result in unhelpful error messages, like:
The cause was that the request body handling system in the
server/authorizer
package did not take gzipped payloads into account. The fix was to borrow the gzip request body handling function fromserver/server.go
, to transparently decompress the body when needed.Fixes: #6804
TODOs