Skip to content
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

Include http request context in decision logs #6750

Merged

Conversation

ashutosh-narkar
Copy link
Member

@ashutosh-narkar ashutosh-narkar commented May 16, 2024

It would be useful if users had the ability to enhance the
decision log with info from the incoming HTTP request such as
headers. This change allows users to configure headers whose
values if present in the incoming HTTP request would be
surfaced via the decision log. This can be extended in the
future to include more context from the request.

Fixes: #6693

@ashutosh-narkar ashutosh-narkar changed the title WIP: Include http request context in decision logs Include http request context in decision logs May 16, 2024
@ashutosh-narkar ashutosh-narkar marked this pull request as ready for review May 16, 2024 23:23
Copy link

netlify bot commented May 16, 2024

Deploy Preview for openpolicyagent ready!

Name Link
🔨 Latest commit 90adba3
🔍 Latest deploy log https://app.netlify.com/sites/openpolicyagent/deploys/66479a0a6337f20008c00296
😎 Deploy Preview https://deploy-preview-6750--openpolicyagent.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@@ -60,6 +60,7 @@ func (h *LoggingHandler) loggingEnabled(level logging.Level) bool {
func (h *LoggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var rctx logging.RequestContext
rctx.ReqID = atomic.AddUint64(&h.requestID, uint64(1))
rctx.HTTPRequestContext = logging.HTTPRequestContext{Header: r.Header.Clone()}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the requested_by field in the decision log, the request context would be available in the log when the log-level is info or higher.

Copy link
Contributor

@johanfylling johanfylling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍
Just a question about log sanitizing.

| `[_].input` | `any` | Input data provided in the policy query. |
| `[_].result` | `any` | Policy decision returned to the client, e.g., `true` or `false`. |
| `[_].requested_by` | `string` | Identifier for client that executed policy query, e.g., the client address. |
| `[_].request_context.http.headers` | `object` | Set of key-value pairs describing HTTP headers and their corresponding values. The header keys in this object are specified by the user as part of the decision log configuration. |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we further clarify to the user to expect a list of values for each header?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

for _, h := range rctx.HTTPRequest.Headers {
values := decision.HTTPRequestContext.Header.Values(h)
if len(values) > 0 {
headers[h] = decision.HTTPRequestContext.Header.Values(h)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be sanitizing these values so a client can't do log injection attacks? Or do we perform global sanitizing somewhere before emitting data to the log?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't do any sanitizing afaict. Anything particular you had in mind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing in particular. In general though, this is a whole category of XSS attacks that target the consumer of the log. In part, this is a consideration for the consumer-side, but it could be argued that OPA, which is generating the log, should take some of the burden to sanitize the content; especially as some of the values are created wholesale by the requesting client, and not OPA.

decisionInfo: &server.Info{Bundles: map[string]server.BundleInfo{"b1": {Revision: "A"}}, HTTPRequestContext: logging.HTTPRequestContext{Header: h2}},
expected: &RequestContext{HTTPRequest: &HTTPRequestContext{Headers: map[string][]string{"foo": []string{"bar"}}}},
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about test cases for when there are incoming headers but the config has

  1. an empty headers list,
  2. no header list but a http entry,
  3. no http entry?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these test cases.

It would be useful if users had the ability to enhance the
decision log with info from the incoming HTTP request such as
headers. This change allows users to configure headers whose
values if present in the incoming HTTP request would be
surfaced via the decision log. This can be extended in the
future to include more context from the request.

Fixes: open-policy-agent#6693

Signed-off-by: Ashutosh Narkar <anarkar4387@gmail.com>
@ashutosh-narkar ashutosh-narkar merged commit a8ac7b3 into open-policy-agent:main May 20, 2024
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make http headers available in the decision-log
2 participants