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: open-policy-agent#6804

Signed-off-by: Philip Conrad <[email protected]>
  • Loading branch information
philipaconrad committed Jun 17, 2024
1 parent b463d30 commit 6805365
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 6805365

Please sign in to comment.