OPA: Mask sensitive data

550 views Asked by At

I want to mask the password in my Open Policy Agent (OPA) logs.

This is my input data:

{
"decision_id":"71e99093-b980-4c67-bd0c-87fcc071571a",
"input":{
  "attributes":{
     .....
     ,
     "request":{
        "http":{
           "body":"{\r\n    \"username\": \"MyUsername\",\r\n    \"password\": \"MySecetPassword\"\r\n}",
           "headers":{
           ....
           },
           "method":"POST",
           "path":"/login",
           "protocol":"HTTP/1.1",
           "scheme":"http",
           "size":"63"
        },
        "time":"2022-09-06T05:51:13.802770Z"
     },
     ...
  },
  "parsed_body":{
     "password":"MySecetPassword",
     "username":"MyUsername"
  },
  "parsed_path":[
     "login"
  ],
  "parsed_query":{
     
  },
  "truncated_body":false,
  "version":{
     "encoding":"protojson",
     "ext_authz":"v3"
  }
},
"labels":{
  "id":"3987b552-f128-47f2-9b96-34289d677d76",
  "version":"0.35.0-envoy"
},
"level":"info",
"metrics":{
  "timer_rego_query_eval_ns":49451,
  "timer_server_handler_ns":395446
},
"msg":"Decision Log",
"path":"istio/authz/allow",
"requested_by":"",
"result":true,
"time":"2022-09-06T05:51:13Z",
"timestamp":"2022-09-06T05:51:13.804132822Z",
"type":"openpolicyagent.org/decision_logs"
}

My OPA mask rule:

mask[{"op": "upsert", "path": "/input/attributes/request/http/body", "value": x}] {
    # conditionally upsert password if it existed in the orginal event
    contains(input.attributes.request.http.body, "password")
    x := "***CENSORED***"
}

mask[{"op": "upsert", "path": "/input/parsed_body/password", "value": x}] {
    # conditionally upsert password if it existed in the orginal event
    input.parsed_body.password
    x := "***CENSORED***"
}

But when OPA checks the request, the sensitive data won't be masked with the new text. Any idea?!

I checked the rule in the The Rego Playground (https://play.openpolicyagent.org) which was fine...

2

There are 2 answers

3
Devoops On BEST ANSWER

From the OPA docs on the topic, you'll see that the original input attribute may be referenced under input.input (i.e. not just input, as that's the input attribute for the masking policy itself).

package system.log

mask["/input/password"] {
  # OPA provides the entire decision log event as input to the masking policy.
  # Refer to the original input document under input.input.
  input.input.resource == "user"
}

Changing input.attributes.request.http.body to input.input.attributes.request.http.body should do it.

0
flo-ferox On

To complete the solution...

The solution from Devoops is correct.

My fault was, that I tried to combine the masking part with the policy. But they have to be in two different files (in to different packages!).