Skip to content

Commit

Permalink
server/authorizer: Fix gzip payload handling.
Browse files Browse the repository at this point in the history
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: #6804

Signed-off-by: Philip Conrad <[email protected]>
  • Loading branch information
philipaconrad committed Jun 17, 2024
1 parent ad1f75d commit 34889a4
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions server/authorizer/authorizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package authorizer

import (
"bytes"
"compress/gzip"
"context"
"io"
"net/http"
Expand Down Expand Up @@ -151,7 +153,6 @@ func (h *Basic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

func makeInput(r *http.Request) (*http.Request, interface{}, error) {

path, err := parsePath(r.URL.Path)
if err != nil {
return r, nil, err
Expand All @@ -164,7 +165,11 @@ func makeInput(r *http.Request) (*http.Request, interface{}, error) {

if expectBody(r.Method, path) {
var err error
rawBody, err = io.ReadAll(r.Body)
plaintextBody, err := readPlainBody(r)
if err != nil {
return r, nil, err
}
rawBody, err = io.ReadAll(plaintextBody)
if err != nil {
return r, nil, err
}
Expand Down Expand Up @@ -277,3 +282,20 @@ func GetBodyOnContext(ctx context.Context) (interface{}, bool) {
}
return input.parsed, true
}

// Note(philipc): Copied over from server/server.go
func readPlainBody(r *http.Request) (io.ReadCloser, error) {
if strings.Contains(r.Header.Get("Content-Encoding"), "gzip") {
gzReader, err := gzip.NewReader(r.Body)
if err != nil {
return nil, err
}
bytesBody, err := io.ReadAll(gzReader)
if err != nil {
return nil, err
}
defer gzReader.Close()
return io.NopCloser(bytes.NewReader(bytesBody)), err
}
return r.Body, nil
}

0 comments on commit 34889a4

Please sign in to comment.