Skip to main content

data-mask

Masks or removes sensitive request data in the log lines, after the upstream has seen it.

Category TransformationAdd it to Route, Service, Consumer, Consumer group, Global rule, Plugin configEngine plugin data-maskPriority 1500

What it does​

data-mask hides parts of a request in the records the loggers on the same route write, for example file-logger. Each rule under Request names a query parameter, a header or a field of the body, and removes it, writes a value over it or replaces what a pattern matches.

The masking reaches the records only. The backend receives the request as the client sent it, card number included, and the client gets the backend's answer unchanged. To keep a value from reaching the backend, take it off the request with proxy-rewrite.

When to use it​

  • Clients of the orders API send card numbers in the body, and the request records must not hold them.
  • Every request carries a bearer token in Authorization, and the records should keep the scheme but not the token.
  • A partner sends an access token as a query parameter, and the records should drop that parameter.
  • A route logs request bodies for debugging, and the password field of a form must stay out of the log.

Not for removing a header or a parameter before the backend receives it — see proxy-rewrite (Rewrites the request URI, method, host and headers before proxying) or changing what the client receives in the answer — see response-rewrite (Rewrites the response status, headers and body).

Set it up​

Hide card numbers and bearer tokens before the request is logged​

The backend still receives the request as it was sent; only what the loggers on the route record is masked.

Fill Request as in the JSON below.

data-mask · as the console saves it
{
"request": [
{
"type": "body",
"body_format": "json",
"name": "$.card.number",
"action": "replace",
"value": "****"
},
{
"type": "header",
"name": "authorization",
"action": "regex",
"regex": "Bearer (.+)",
"value": "Bearer ****"
}
]
}

Things to know​

  • Request — Masking runs after the answer: the upstream and the client saw the value, and only the lines the loggers write carry the mask.
  • Request — With the example's rules, the backend receives 4111111111111111 as the card number, and the record the logger writes carries **** in its place and Bearer **** as the Authorization header.
  • Regex — Only the part the pattern matches changes: Bearer (.+) with the value Bearer **** keeps the scheme in the record and hides the token.
  • Name — In a JSON body the name is a path into the document: $.card.number masks the number inside card.
  • Request — A rule that lacks a field its Type or Action needs is refused when you save, and the refusal does not say which field is missing.
  • Type — Only a query parameter, a header or the body can be masked; a rule on a cookie is refused when you save.
  • Value — A replace rule without a Value is refused when you save.
  • AdviceCheck the first records a route writes after you add a rule, before you rely on the mask.

Settings​

The fields as the console shows them, section by section.

Requestrequestarray of objects

Rules applied in order to the logged request. A body rule needs a Body format, a regex rule a Regex and a Value, a replace rule a Value. When one is missing, the refusal does not say which.

Each item:
Typerequest[].typestringRequired

Where the field lives: a query parameter, a request header or the request body.

one of body, header, query
Actionrequest[].actionstringRequired

Remove drops the field, replace writes the value below over it, and regex substitutes the pattern.

one of regex, remove, replace
Namerequest[].namestringRequired

A parameter or header name, and a JSONPath expression such as $.card.number where a JSON body is read.

Valuerequest[].valuestringRequired when action is regex, or when action is replace

What replace writes, and what regex puts in place of the pattern.

Regexrequest[].regexstringRequired when action is regex

Only the first match is replaced, and a pattern that does not compile leaves the value as it was.

Body formatrequest[].body_formatstringRequired when type is body

How the body is read; a rule over a body is refused without it.

one of json, urlencoded
Body size limitmax_body_sizeintegerdefault 1048576

The largest JSON body, in bytes, that is masked. A larger one is logged unmasked, and only the gateway's error log says so.

over 0
Form fields readmax_req_post_argsintegerdefault 100

How many fields of a form-encoded body are read. Later fields stay unmasked, and zero reads them all.

at least 0

Every plugin also has Enabled, Priority, Filter, Error response and Pre-function: see Plugin execution settings.

G8 dev · Apache APISIX® 3.19.0
Apache, Apache APISIX and APISIX are trademarks of The Apache Software Foundation.
Facts
Category
Transformation
Add it to
Route, Service, Consumer, Consumer group, Global rule, Plugin config
Engine plugin
data-mask
Priority
1500