Masking and hiding data

This page applies to Apigee and Apigee hybrid.

View Apigee Edge documentation.

When you debug APIs calls in Apigee, the content can sometimes contain sensitive data, such as credit cards or personally identifiable health information (PHI) that must be masked.

Apigee provides different ways of masking or hiding sensitive data from debug sessions. If you use masking for data collected in debug sessions, Apigee performs the masking in the gateway nodes, before transmitting the debug session data to the control plane.

Masking sensitive data

Apigee enables you to define mask configurations to mask specific data in trace and debug sessions. When data is masked, it is replaced with asterisks in the trace output. You can mask sensitive data and keep non-sensitive data unchanged. For example:

<ServiceRequest>
  <request-id>B540A938-F551</request-id>
  <customer-name>**********</customer-name>
</ServiceRequest>

The mask configuration is a singleton resource that you define at the environment level. By default, no data masking is in effect.

Data masking applies only to data captured in a debug session for an API proxy. Data masking does not affect the data that gets sent to targets or client applications. If you change your data masking configuration, you must start a new debug session to see the effect of your change.

Structure of a mask configuration

Mask configurations are JSON-formatted files that enable you to identify sensitive data in the following sources:

The following provides an example of the basic structure of a mask configuration in JSON format. For more information about the mask configuration fields shown in the example, see DebugMask.

{
  "namespaces": {
    "myco": "http://example.com"
  },
  "requestXPaths": [
    "/myco:Greeting/myco:User"
  ],
  "responseXPaths": [
    "/myco:Greeting/myco:User"
  ],
  "faultXPaths": [
    "/myco:Greeting/myco:User"
  ],
  "requestJSONPaths": [
    "$.store.book[*].author"
  ],
  "responseJSONPaths": [
    "$.store.book[*].author"
  ],
  "faultJSONPaths": [
    "$.store.book[*].author"
  ],
  "variables": [
    "request.header.user-name",
    "request.formparam.password",
    "myCustomVariable"
  ]
}

Viewing the mask configuration in an environment using the API

To view the mask configuration in an environment, issue a GET to the following resource:

/organizations/{org}/environments/{env}/debugmask

For example:

curl "https://apigee.googleapis.com/v1/organizations/myorg/environments/test/debugmask" \
  -X GET \
  -H "Authorization: Bearer $TOKEN"

Where $TOKEN is set to your OAuth 2.0 access token, as described in Obtaining an OAuth 2.0 access token. For information about the curl options used in this example, see Using curl. For a description of environment variables you can use, see Setting environment variables for Apigee API requests.

The following provides an example of the response:

{
  "name": "organizations/myorg/environments/test/debugmask"
  "namespaces": {
    "myco": "http://example.com"
  },
  "requestXPaths": [
    "/myco:Greeting/myco:User"
  ],
  "responseXPaths": [
    "/myco:Greeting/myco:User"
  ]
}

Updating the mask configuration in an environment using the API

To update the mask configuration singleton resource in an environment, issue a PATCH to the following resource:

/organizations/{org}/environments/{env}/debugmask

Optionally, you can pass the following query parameters:

For example:

curl "https://apigee.googleapis.com/v1/organizations/myorg/environments/test/debugmask" \
  -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-type: application/json" \
  -d \
  '{
     "namespaces": {
       "ns1": "http://example.com"
     },
     "requestXPaths": [
       "/ns1:employee/ns1:name"
     ]
   }'

Where $TOKEN is set to your OAuth 2.0 access token, as described in Obtaining an OAuth 2.0 access token. For information about the curl options used in this example, see Using curl. For a description of environment variables you can use, see Setting environment variables for Apigee API requests.

Masking namespace-scoped XML

If you want to mask XML data and that data uses XML namespaces, your mask configuration must reference those namespaces with the namespaces element. This is true whether the XML payload uses a default namespace, or a namespace prefix.

For example, suppose you want to mask the employee name in the request payload, and the XML does not use XML namespaces:

<employee>
  <name>Shanmu Tharman</name>
  <age>50</age>
</employee>

Therefore, the debugmask configuration doesn't require the namespaces element:

{
  "requestXPaths": [
    "/employee/name"
  ]
}

If the XML payload uses namespaces with prefixes:

<cym:employee xmlns:cym="http://cymbalgroup.com" xmlns:id="http://cymbalgrou>p.c<om/iden>tity"
  i<d:nameSh>anm<u Thar>ma<n/id:na>m<e
  id:age50/>id:age
/cym:employee

Then the mask configuration should contain the namespaces element. You may choose any valid namespace prefix in the debugmask configuration; the namespace prefix in the debugmask configuration may be the same as the namespace prefix used in the XML, but that is not required.

{
  "namespaces": {
    "cym": "http://cymbalgroup.com",
    "idns": "http://cymbalgroup.com/identity"
  },
  "requestXPaths": [
    "/cym:employee/idns:name"
  ]
}

If the XML Payload uses a namespace with no prefix, meaning the default namespace:

<employee xmlns="http://cymbalgroup.com" xmlns:id="http://cymbalgrou>p.c<om/iden>tity"
  i<d:nameSh>anm<u Thar>ma<n/id:na>m<e
  id:ag>e50/id:age
/employee

Then the debugmask configuration must still define a prefix in the namespaces element corresponding to that default namespace. You can use any unique prefix you like.

{
  "namespaces": {
    "p1": "http://cymbalgroup.com",
    "id": "http://cymbalgroup.com/identity"
  },
  "requestXPaths": [
    "/p1:employee/id:name"
  ]
}

Other Configuration Notes

Hiding sensitive data

In addition to masking, you can prevent sensitive data from even appearing in the Trace tool and debug sessions by choosing a name that begins with private. for your custom variables.

For example, when using the Key Value Map Operations policy to retrieve a value from a key value map, you may choose the variable name as follows to ensure the value does not appear in Trace or debug sessions:

<KeyValueMapOperations name='KVM-Ge>t-1&#<39;
 >   Scopeenv<ironme>nt/Sc<ope
    ExpiryTi>meI<nSecs300/ExpiryTi>meInS<ecs
   > MapName<settings>/MapN<ame
    Get assignTo='private>.privat<eke>y'
  <    Key
 >       Paramete<rrsa_priva>te_key/<Para>meter<
   >   </Key
    /Get
  /KeyVa>lueMapOperations

Variables without the private. prefix are displayed in clear text in Trace and debug sessions even if the data originates from an encrypted data store such as a key value map. Use masking if you want to mask these values.