Vault Proxy
11 min read
In certain cases, your application may need to communicate sensitive data (like PII or PCI data) to third-party services (like payment gateways). With Footprint's Vault Proxy, you can avoid sensitive data touching your application code and infrastructure in plaintext. Not only does vault proxying help strengthen your security posture and avoid data leaks/compromises, but this also helps you satisfy strict compliance requirements (like PCI) by never having this data touch your networks or infrastructure.
The vault proxy supports the following main features:
Feature | Overview |
---|---|
Any HTTPS URL and method | Works with any HTTPS resource |
Flexible detokenization | Supports secure detokenization for any type of request body, content-type agnostic |
Fixed IP range | Requests from Footprint Vault Proxy always come from a fixed set of IP addresses that you can whitelist on the proxy destination |
Custom headers | Attach custom headers |
Authentication secrets | Securely attach custom authentication secrets |
Client Certififcates (mTLS) | Securely attach a ceritificate + key for mTLS Client Certififcate authentication connections |
Server Certificate Pinning | Specify one or more Root CAs and leaf certificates to securely validate the destination |
Ingress Vaulting | Securely vault data that comes back on the ingress. Support for JSONPath (XPath and Regex coming soon) rules |
Configuration
The proxy can be configured in two main ways: define the configuration using the dashboard/admin API or dynamically specify all the configuration values via headers "just-in-time."
Both methods support the same fundamental capabilities, but the two options offer flexibility in defining proxy configurations and simplifying the management of sensitive data and authentication credentials.
Header | Usage | Description |
---|---|---|
x-fp-proxy-target-url | Required if "just-in-time" | The target destination HTTPS URL to which the request will be routed |
x-fp-proxy-id | Required if proxy configuration | The id of the Proxy Configuration declared in the developer dashboard or created via the admin API |
Basic Proxying
Making the proxy request
A vault proxy request consists of a typical authenticated HTTP POST
request to the /proxy
endpoint of the Footprint API.
For example:
bash
curl https://api.onefootprint.com/proxy \ -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \ -X POST \ -H 'x-fp-proxy-target-url: https://payments.acmebank.com' \ -H 'x-fp-proxy-fwd-custom-header: custom value' \ -H 'x-fp-proxy-fwd-content-type: application/json' \ --data '{ "full_name": "{{ fp_id_tctecBEvGc98V7Vx4MhZU.id.first_name }} {{ fp_id_tctecBEvGc98V7Vx4MhZU.id.last_name }}", "last4_ssn": "{{ fp_id_tctecBEvGc98V7Vx4MhZU.id.ssn4 }}", "cc": "{{ fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card }}", "cc_exp": "{{ fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card_exp }}", "cc_cvc": "{{ fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card_cvc }}" }'
The above request detokenizes each of the fields in the request body in the Footprint vault enclave, and then makes an upstream request with the corresponding in-place-updated plaintext body to the target (in this case https://payments.acmebank.com
) with custom headers 'Custom-Header: custom value'
and 'Content-type: application/json'
.
You can add additional control headers to configure how the upstream proxy request behaves:
Header | Required? | Function |
---|---|---|
x-fp-proxy-fwd-<HEADER> | Optional | Sends a header named <HEADER> with the corresponding value |
x-fp-proxy-method | Optional | Selects the HTTP Method Verb to use (defaults to POST if unspecified) |
x-fp-proxy-access-reason | Optional | The decryption reason to use for access/security logs during detokenization. Defaults to empty/no-reason. |
Token body template format
Footprint's Vault Proxy will attempt to substitute in-place any tokens found in the body of the request with the corresponding detokenized, plain-text values. A token expression starts with {{
and ends with }}
.
Footprint's vault proxy APIs support two methods of specifying tokens in the request body:
Fully-qualified tokens
Each token is specified as {{ <footprint_user_token>.<data_identifier> }}
. <footprint_user_token>
is the user's footprint token. <data_identifier>
can be any identity KYC attribute (prefixed with id.
) or any custom attribute defined by you (prefixed with custom.
)
Fully-qualified format |
---|
{{ fp_id_tctecBEvGc98V7Vx4MhZU.id.last_name }} |
{{ fp_id_tctecBEvGc98V7Vx4MhZU.id.ssn9 }} |
{{ fp_id_tctecBEvGc98V7Vx4MhZU.id.dob }} |
{{ fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card }} |
Inferred-user tokens
If you're operating on a single Footprint user vault, you can simplify the token body formatting by specifying the following header to identify which user vault is referenced.
Header | Value |
---|---|
x-fp-proxy-footprint-token | The Footprint user token used to infer request tokens |
In this case, the token can omit the <footprint_user_token>
above and specify tokens as {{ <data_identifier> }}
.
Inferred-user format |
---|
{{ id.last_name }} |
{{ id.ssn9 }} |
{{ id.dob }} |
{{ custom.credit_card }} |
Advanced proxy features
Footprint's vault proxy supports advanced configurations such as mTLS (client certificates), certificate pinning (custom server certificates), and automatically selecting and tokenizing parts of the response data and storing it in the vault. Note that the guide below shows how to configure these advanced features using "just-in-time" headers, but we recommend specifying these instead using the developer dashboard for simplicity and greater security (you won't need to manage authentication secrets for the destination service).
Client certificate authentication (mTLS)
Optionally, specify a client certificate and key in order to connect securely to the proxy destination using Mutual TLS (mTLS).
Only a single cert/key pair can be supplied. Note the format of the certificate/key is in PEM and then Percent-encoded.
Service certificate pinning and Root CAs
Optionally, specify zero or more server certificates or Root CAs to pin the upstream proxy request server certificate validation.
If multiple certificates are specified, all the supplied certificates will be used in the validation process and as long as a single certificate can validate the incoming certificate chain, the connection will succeed. Note the format of the certificate/key is in PEM format and then Percent-encoded
.
Ingress Vaulting
Ingress vaulting rules define how to tokenize and vault certain sensitive fields that appear in the response from the upstream proxy destination. This allows the vault proxy to not only de-tokenize outgoing data but to also tokenize incoming data to vault it just in time.
For simplicity, you can also define all of your ingress vaulting rules via the developer dashboard or admin API and simply reference the proxy configuration via the x-fp-proxy-id
header.
However, when you declare ingress vaulting rules in the configuration, you still need to denote in the proxy request into which Footprint user vault to tokenize the data. Therefore, the following header value is required when using ingress rules for pre-configured proxy:
Header | Format | value |
---|---|---|
x-fp-proxy-footprint-token | <fp_id> | The Footprint user token for which the vaulting rules apply too |
For example: add the header 'x-fp-proxy-footprint-token: fp_id_tctecBEvGc98V7Vx4MhZU'
where the rule in the proxy configuration would be defined as custom.credit_card_number=$.data.card.number
.
Just-in-time ingress vaulting
The format of the rule is defined as <footprint_token_id>.custom.<property_name>=<path-to-value>
where the path format is relative to the content-type being used.
Note if using a dynamic proxy configuration (just-in-time), you must specify a single x-fp-proxy-ingress-content-type
header if one more x-fp-proxy-ingress-rule
headers are present.
Ingress rules use a similar token format to the body format above, except without the {{
and }}
delimiters.
JSONPath
Currently ingress only supports JSON and the associated JSONPath format for specifying a target value.
bash
-H 'x-fp-proxy-ingress-rule: fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card_number=$.data.card.number'
The above token would extract 4242424242424
from the following response object and vault it under the custom.credit_card_number
field for fp_id_tctecBEvGc98V7Vx4MhZU
's user vault.
json
{ "data": { "card": { "number": "4242424242424", "exp": "04/24" }, "processor": "amex" } }
More examples |
---|
fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card.number=$.data.card.number |
fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card.exp=$.data.card.expiration |
fp_id_tctecBEvGc98V7Vx4MhZU.custom.credit_card.cvc=$.data.card.security_code |
Header and Configuration Reference
Below find the complete reference guide of headers and their uses for both configuring and invoking the proxy "just-in-time". Note that some values can be defined in the proxy configuration settings and do not need to be sent each time.
Header | Usage | Description |
---|---|---|
x-fp-proxy-target-url | Required if "just-in-time" | The target destination HTTPS URL to which the request will be routed |
x-fp-proxy-id | Required if proxy configuration | The id of the Proxy Configuration declared in the developer dashboard or created via the admin API |
x-fp-proxy-method | Optional. | Selects the HTTP Method Verb to use (defaults to POST if unspecified). Overrides a configuration's value if present. |
x-fp-proxy-fwd-<HEADER> | Optional. Multiple allowed. | Sends a header named <HEADER> with the corresponding value |
x-fp-path-and-query | Optional. | Use this header to customize/add additional path and/or query parameters to your existing proxy target URL |
x-fp-proxy-footprint-token | Optional. | The Footprint user token for which the proxy rules apply to. Required if tokens in the body dont specify an fp_id_ prefix. |
x-fp-proxy-access-reason | Optional. | The decryption reason to use for access/security logs during detokenization. Defaults to empty/no-reason. |
x-fp-proxy-client-cert | Optional. Percent-encoded PEM | The client certificate to use |
x-fp-proxy-client-key | Optional. Percent-encoded PEM | The client certificate private key to use |
x-fp-proxy-pin-cert | Optional. Percent-encoded PEM. Multiple allowed. | A root CA certificate or self-signed certificate to validate the certificate of the server |
x-fp-proxy-ingress-content-type | Optional. | The content-type of the response to process ingress rules. Currently only json is supported, but regex and xml are coming soon! |
x-fp-proxy-ingress-rule | Optional. <token>=<path> . Multiple allowed. | Ingress rule itself, assigning a specific namepspeced token to the corresponding path of the value to vault |
Configure via Admin API
In some cases you may want to create a proxy configuration in an API call.
First specify your proxy configuraton object
json
{ "url": "https://api.acmepayments.com/v1/generate_card", "method": "POST", "name": "Acme Payment Gateway Proxy", "access_reason": "Generate credit card number for user", "pinned_server_certificates": [ "-----BEGIN CERTIFICATE-----\nMIIFiDCCA3CgAwIBAgIJAJONEl2..." ], "client_identity": { "certificate": "-----BEGIN CERTIFICATE-----\nMIIFa...", "key": "-----BEGIN PRIVATE KEY-----\nMIIJRAIBADAN..." }, "headers": [ { "name": "content-type", "value": "application/json" } ], "secret_headers": [ { "name": "x-acme-api-key", "value": "6WvVKOtTi9NAvJTfPDxZOPwa..." } ], "ingress_settings": { "content_type": "json", "rules": [ { "token": "custom.credit_card", "target": "$.data.card_number" } ] } }
Note that pinned_server_certificates
and client_identity
parameters are optional settings and can be omitted. Only uses these if the third-party destination requires mTLS and/or uses custom server certificate CAs.
POST the Proxy Configuration
bash
curl -X POST -u <YOUR_API_KEY>: https://api.onefootprint.com/org/proxy_configs -H 'Content-Type: application/json' -d @object.json { "id":"proxy_id_AY5ec7I5QDUFWG8BAQG78k", ... }
Take note of the id
that comes back, for example: proxy_id_AY5ec7I5QDUFWG8BAQG78k
. You will use this to invoke the proxy.
Invoke the Proxy
In this example we invoke the proxy to generate a credit card number for user by securely passing tokens for the user's PII and on the recieving end vaulting the resulting card number to the user's vault.
bash
curl -X POST -u <YOUR_API_KEY>: \ -H 'x-fp-proxy-id: proxy_id_AY5ec7I5QDUFWG8BAQG78k' \ -H 'x-fp-proxy-footprint-token: fp_id_ABoOtcf9DbF6shyLNONT3n' \ --data '{ "ssn_last_four": "{{ id.ssn4 }}", "date_of_birth": "{{ id.dob }}", "name_on_card": "{{ id.first_name }} {{ id.last_name }}", "data": { "card_number": "1234-4567-8910"} }'
Playground
Use our ditto
server to test your proxy configurations. Sending requests to https://ditto.footprint.dev
will replay the headers and body of any incoming requests. Give it a try!
Basic usage
bash
$ curl -i -X POST https://ditto.footprint.dev -H 'Test-Header: FootprintRocks' --data '{"hello": "world" }' test-header: FootprintRocks content-type: application/x-www-form-urlencoded {"hello": "world" }
By using https://ditto.footprint.dev
as your proxy destination target, you can test that the proxy decryption and token templating is working as expected.
Testing with client certificates
The footprint ditto server also supports testing mTLS with client certificates: use https://ditto.footprint.dev:8443
(port 8443). Note that the server certificate is self-signed so you must either trust it or pin it the configuration.
bash
$ curl --cert client.crt --key client.key -i -k -X POST https://ditto.footprint.dev:8443 -H 'Test-Header: FootprintRocks' --data '{"hello": "world" }' x-ditto-client-cert-serial: 12431179266346922388 test-header: FootprintRocks content-type: application/x-www-form-urlencoded {"hello": "world" }
Note the ditto server echoes the client certificate SERIAL (if a client certificate is used) in the special header x-ditto-client-cert-serial
.