Skip to main content

Developer Guide

Welcome to the InCountry documentation site. Here we collected the basic principles and recommendations on how to quickly get started with InCountry Data Residency-as-a-Service (DRaaS).

  1. Web application context
  2. Prerequisites
  3. Mapping application fields to InCountry record structure
  4. Run CRUD requests through Border
  5. Swapping URL for your API calls
  6. Adding CORS headers
  7. How to update the UI to show masked fields and disable fields for specific users
  8. Run search through the Border
  9. File management with REST API services
  10. For dashboard and reports that use aggregated data
  11. How to call resident functions against protected data to stay compliant
  12. Configure outbound email to use redacted email addresses and fields
  13. How to migrate your existing data and tokenize migrated fields within your existing database
  14. How to migrate configuration of environments

1. Web application context

Let’s imagine that we have a generic web application that manages customers originating from different countries. After introduction of new data regulations, we need to localize regulated data in its country of origin and implement additional controls to ensure that regulated data does not leave its domestic borders or imply additional restrictions on its processing.

The application handles regulated data (personally identifiable information (PII)) of customers, and some of the customers come from countries with stringent data regulations (such as China). The application stores the following information about customers:

  • First name (firstName (PII))

  • Last name (lastName (PII))

  • Email (email (PII))

  • Mobile phone (phone (PII))

  • Vehicle (vehicle)

  • Yearly spending (yearlySpending)

  • Country (country)

Some fields are classified as regulated because contain PII data. For Chinese customers, this information must be localized within its domestic borders. Let’s explore how InCountry DRaaS can be integrated with this application.

2. Prerequisites

Before you start modifying your web application, let’s complete some routine tasks including the following:

  1. Register an account on InCountry Portal.

  2. Create an environment.

  3. Activate the country where you want to store regulated data.

3. Mapping application fields to InCountry record structure

By default, InCountry DRaaS stores regulated data as records in its data vault. The record has a specific structure having different sets of fields for storing various data formats, as follows:

Default record structure

FieldTypeQtyStorageSpecifics
record_keystring1HashedThis is a unique identifier of the record which is returned by the REST API. This field is used to store the primary key of the record. This field is used as an alias for the deprecated key field.
bodystring1EncryptedYou can also stringify data in the JSON format and save it within this field.
precommit_bodystring1EncryptedYou can use this field to store some service information about the record.
profile_keystring1HashedThe unique identifier of the data record in an external system. It can be used for storing any other data string if needed.
parent_keystring1HashedKey of the parent record which the current record is attributed to.
range_keyNinteger10PlainN can be between 1 … 10. You can use up to 10 fields. The range_keyN fields are used for value range filtration of numerical values.
service_keyNstring5HashedN can take from 1 to 5. You can have up to 5 fields. The service_keyN fields can be used for storing additional text information.
keyNstring20Hashed / PlainN can take from 1 to 20. You can use up to 20 fields. This value can be hashed or remain as a plain value depending on your configuration. This field can be used for record lookup.
decimal_keyNdecimal20PlainN can take from 1 to 20. You can use up to 20 fields. The decimal_keyN fields are used for value range filtration of numerical values.
created_atstring (date-time)1PlainThe timestamp in the ISO-8601 format when a record was created.
updated_atstring (date-time)1PlainThe timestamp in the ISO-8601 format when a record was updated.
expires_atstring (date-time)1PlainThis field determines the date and time when the record will be automatically deleted from the InCountry Vault.
countryISO country code (lowercase)1PlainCountry where a new record is stored.
attachmentsobject1-For the details on the attachments field, please see the Management of attachments section.

To simplify the management of records and attribution of values to specific fields, you can create aliases for default field names. InCountry DRaaS will automatically map values coming to field aliases to the original field names, so you can reference fields based on information they store.

Management of key-alias mappings is performed on the InCountry Portal at the environment level.

Management of key-alias mappings

  1. Open the environment where you want to specify key-alias mappings.

  2. Click the Fields icon.

  3. Specify the field alias and value format, then select the original field for mapping.

  4. Save mappings.

Using key-aliases

Once you have configured key-aliases, you can use them when handling requests to REST API. You don’t need to specify original field names and use aliases instead.

4. Run CRUD requests through Border

Now when we have created the key-alias mappings, we can proceed with implementation of data residency capabilities in our web application. As the quickest and simplest solution for capturing regulated data and its saving to the InCountry we can choose Border.

note

When implementing Border for handling requests containing regulated data, you need to consider the following limitations:

  1. JSON or x-www-form-urlencoded data structure. The request payload and response body must be in the JSON format only. Other data formats will be ignored and will be passed as is.

  2. Bulk creation or update of records is not supported.

  3. Field-based policy is not supported intentionally. Border does not regulate access to specific fields of the record for each user, considering user-specific permissions. Border just unredacts the response body that your application backend returns. Your application backend must consider this and must return within the response body only the fields the user can view, other fields must be removed. For example, the user is not intended to see the Salary field when viewing the list of users, so the application backend when returning the response body must exclude the Salary field, and otherwise Border may reveal the actual clear-text values.

  4. The ID of a newly created record must be present in the response to the request for creating a record.

  5. The ID of the record should be present in the body of a request or in the URL request (for example, PUT /customers/id123) in data requests for updating records.

  6. The ID of the record should be present in the request URL for data requests for deleting records.

Let’s get started with Border, you need to do the following preliminary steps:

  1. Open the country where you want to implement Border.

  2. Create a Border service.

Having created a Border service, we can proceed with implementing endpoints through which we will route our application requests containing regulated data.

Creation of Border endpoints

Setting up a Border configuration

  1. Create a new Border endpoint.

  2. Enter the endpoint name.

  3. Enter the URL of your web application.

Before implementing data residency capabilities within this web application, let’s identify data requests that handle regulated data. In the case of our web application, all the requests deal with customer data and regulated values in particular. Let’s check how an original request looks like and create redaction and unredaction rules for each request.

Creating a new customer

URIHTTP method
/api/customersPOST

The request payload looks as follows:

{
"firstName": "Liu",
"lastName": "Chang",
"email": "liu_chang@qq.com",
"phone": "+8613260710890",
"vehicle": "Haval",
"yearlySpending": 123,
"country": "cn"
}

The response body looks as follows:

{
"customer_id" : "85d117f8-1b1a-11ee-be56-0242ac120002",
"firstName": "Liu",
"lastName": "Chang",
"email": "liu_chang@qq.com",
"phone": "+8613260710890",
"vehicle": "Haval",
"yearlySpending": 123,
"country": "cn"
}

Updating a customer

URIHTTP method
/api/customers/{customer_id}PUT

The request payload looks as follows:

{
"firstName": "Liu",
"lastName": "Chang",
"email": "liu_chang@qq.com",
"phone": "+8613260710890",
"vehicle": "Changan",
"yearlySpending": 123,
"country": "cn"
}

The response body looks as follows:

{
"customer_id" : "85d117f8-1b1a-11ee-be56-0242ac120002",
"firstName": "Liu",
"lastName": "Chang",
"email": "liu_chang@qq.com",
"phone": "+8613260710890",
"vehicle": "Changan",
"yearlySpending": 123,
"country": "cn"
}

Viewing a customer

URIHTTP method
/api/customers/{customer_id}GET

The response body looks as follows:

{
"customer_id" : "85d117f8-1b1a-11ee-be56-0242ac120002",
"firstName": "Liu",
"lastName": "Chang",
"email": "liu_chang@qq.com",
"phone": "+8613260710890",
"vehicle": "Changan",
"yearlySpending": 123,
"country": "cn"
}

Deleting a customer

URIHTTP method
/api/customers/{customer_id}DELETE

Save the Border endpoint. The resulting Border endpoint setup will look similar to the one displayed:

Example of Border configuration

{
{
"name": "customers",
"target": "https://bestcrm.com",
"redactions": [
{
"collectionName": "customers",
"entityErrorCorrectionFieldPath": "$.email",
"entityIdPath": "$.id",
"method": "POST",
"path": "/api/customers/",
"searchable": {
"key5": "$.firstName",
"key6": "$.lastName",
"key7": "$.email",
"key8": "$.phone"
},
"strategies": [
{
"path": "$.firstName",
"strategy": "alphaNumericPersistent",
"strategyOptions": {
"persistentTokenSalt": "a4b82be3242049d6b3258b8fb35f6130",
"storeField": true
}
},
{
"path": "$.lastName",
"strategy": "alphaNumericPersistent",
"strategyOptions": {
"persistentTokenSalt": "a4b82be3242049d6b3258b8fb35f6130",
"storeField": true
}
},
{
"path": "$.email",
"strategy": "emailPersistent",
"strategyOptions": {
"persistentTokenSalt": "a4b82be3242049d6b3258b8fb35f6130",
"storeField": true
}
},
{
"path": "$.phone",
"strategy": "numeric",
"strategyOptions": {
"storeField": true
}
}
],
"globalEntityId": true
},
{
"collectionName": "customers",
"entityErrorCorrectionFieldPath": "$.email",
"entityIdPath": "$.id",
"method": "PUT",
"path": "/api/customers/(.+)",
"searchable": {},
"strategies": [
{
"path": "$.firstName",
"strategy": "alphaNumericPersistent",
"strategyOptions": {
"persistentTokenSalt": "a4b82be3242049d6b3258b8fb35f6130",
"storeField": true
}
},
{
"path": "$.lastName",
"strategy": "alphaNumericPersistent",
"strategyOptions": {
"persistentTokenSalt": "a4b82be3242049d6b3258b8fb35f6130",
"storeField": true
}
},
{
"path": "$.email",
"strategy": "emailPersistent",
"strategyOptions": {
"persistentTokenSalt": "a4b82be3242049d6b3258b8fb35f6130",
"storeField": true
}
},
{
"path": "$.phone",
"strategy": "numeric",
"strategyOptions": {
"storeField": true
}
}
],
"globalEntityId": true
},
{
"collectionName": "65325452-2340-4797-8083-a8c452aa91f2",
"isDeleteRequest": true,
"method": "DELETE",
"path": "/api/customers/(.+)",
"strategies": [],
"globalEntityId": true,
"searchable": {}
}
],
"unredactions": [
{
"collections": [
{
"entityErrorCorrectionFieldPath": "$.email",
"entityIdPath": "$.id",
"name": "customers",
"strategies": [
{
"originalPath": "$.firstName",
"path": "$.firstName"
},
{
"originalPath": "$.lastName",
"path": "$.lastName"
},
{
"isErrorCorrectionField": true,
"originalPath": "$.email",
"path": "$.email"
},
{
"originalPath": "$.phone",
"path": "$.phone"
}
],
"globalEntityId": true
}
],
"method": "GET",
"path": "/api/customers/(.+)"
}
]
}
}

5. Swapping URL for your API calls

As the result, after saving the Border endpoint you will get a Border URL address through which you need to route requests with regulated data. You need to apply a new request path only to requests that were specified in the Border endpoint.

Within your web application, you need to do the following:

  1. Create a separate field (for regulated records) that will store the country attribution. Depending on the value within this field, your web application will run a normal flow or a flow to handle records through Border and save or query clear-text values to or from InCountry DRaaS.

  2. Implement a static function that returns a URL for the request based on the record’s country attribution.

const get_border_url = (country, client_id) => `https://${country}-proxy-mt-01.api.incountry.io/x-inc-${client_id}`;

So, before integration with InCountry DRaaS, your web application was using one URL for the same request, as follows:

GET https://webapplication.com/api/customers/85d117f8-1b1a-11ee-be56-0242ac120002

After integration with InCountry DRaaS, you will have two URLs for request execution:

  1. for non-regulated records: a request is executed through the web application’s backend:

    GET https://webapplication.com/api/customers/85d117f8-1b1a-11ee-be56-0242ac120002
  2. for regulated records: a request is proxied through the Border:

    GET https://cn-border-incountry.com/x-inc-<UUID>/api/customers/85d117f8-1b1a-11ee-be56-0242ac120002
info

We recommend that you add URL requests to the constants within your web application code.

Warning

How to handle situations when you do not know what country the record is attributed to?

In your REST API calls that return record for rendering lists of records or when querying a specific record, you need to add a country as a returned value if it’s not present. Otherwise, you need to make two calls:

  1. One against your application backend (to query records from the app database).

  2. The other against Border from the application frontend (to unredact regulated records).

BEFORE:

Return

{lastName =Chang, firstName =Lui}

AFTER:

Return

{lastName =Chang, firstName =Lui, country = “cn”}

6. Adding CORS headers

In some cases, you may have to override CORS policies that are proxied through the Border. For doing this:

  1. Edit the Border endpoint.

  2. Check the Enable CORS box.

  3. Specify the Access-Control-Allow-Origin header.

  4. Save the Border endpoint.

info

If you don’t override CORS headers through the Border endpoint but specify them on your application backend, then Border will just proxy request with their CORS headers to your application frontend from the backend.

info

If you don’t override CORS headers through the Border endpoint and don’t specify them on your application backend, then Border will apply the default headers, as follows:

Access-Control-Allow-Origin: '*' Access-Control-Allow-Credentials: 'true' Access-Control-Allow-Headers: 'Origin, Content-Type, Accept'

7. How to update the UI to show masked fields and disable fields for specific users

Your application backend should regulate what records are visible to this or that user according to an ACL (access control layer) implemented within your application, while Border will unredact the response body as-is without checking user’s permissions.

How to mask values for users requesting regulated records outside the country of origin?

By default, Border unredacts regulated values without checking whether the user requesting them originates from the country of origin. To avoid situations, when you may expose regulated records outside their country of origin, you can use the masking option when configuring the Border endpoint.

In this case, Border will check the IP address of the requestor and check whether it matches or not the record’s country of origin. If it matches, then Border will return a clear-text value, otherwise it will return the masked value to the application frontend for rendering to this user.

Important

Also, your application must know which fields are redacted/masked and which fields are not allowed for some actions (such, as editing), when you configure the Border endpoint. All such limitations and restrictions must be implemented within your application, so Border will just redact the ingress data and unredact egress data without checking what the current user can do and what cannot do.

8. Run search through the Border

Ok, you configure your CRUD operations through Border successfully. Now, how to do a search? How to authorize access to records and fields in the records? You have two options to achieve this:

  1. Run search only by regulated fields stored in InCountry;

  2. Run search records by both regulated and non-regulated fields.

Search only by regulated fields stored in InCountry

You should implement an endpoint in your backend which will accept a list of record IDs from the Border and either approve/disapprove it based on its own ACLs for chosen records or filter it removing record ID for which the user (with provided Auth header) has no access. The example of the endpoint:

POST https://webapplication.com/api/filter-ids
Authorization: Bearer <TOKEN_FROM_INITIAL_REQUEST>
{
ids: ['id1', 'id2', ..., 'idN']
}

Response variant 1: HTTP 200/422 with empty body
Response variant 2: HTTP 200
{
ids: ['id2', 'id10', ..., 'idM']
}

In the result, the response for search request through Border will be:

{
"meta": {
"total": 800,
"count": 500,
"limit": 500,
"offset": 0,
},
"data": [
{
"record_key": "id2",
"key1": "FooBarBaz",
"key2": "...",
"profile_key": "...",
"...": "..."
}, {
"record_key": "id10",
"key1": "1234 FooBar",
"key2": ...,
"profile_key": "...",
"...": "..."
}, {
"record_key": "idM",
"key1": "abcdefoobarqwerty",
"key2": "...",
"profile_key": "...",
"...": "..."
}
]
}

Search records by both regulated and non-regulated fields

You should implement an endpoint in your backend which will accept a list of record IDs from the Border with optional additional filters and return the list of records/resources for which the user (with provided Auth header) has no access.

For example, the customer wants to find all customer with the name “Liu” (regulated field) and car “Haval” (non-regulated field).

1. Request to the Border:
POST https://cn-proxy-mt-01.incountry.io/x-inc-<UUID>/users/search
{
name: "Liu",
vehicle: "Haval"
}

2. The Border sends a dummy auth request to your backend application
POST https://webapplication.com/api/dummy-auth
Authorization: Bearer <TOKEN_FROM_INITIAL_REQUEST>
=> HTTP 200 OK

3. The Border looks for all records where name is "Liu" and
gets the list of ids: 'id1', 'id2', 'id3'

4. The Border sends request to your application backend with parameters
{
ids: ['id1', 'id2', 'id3']
vehicle: 'Haval'
}

GET https://webapplication.com/api/customers/search?id=id1&id=id2&id=id3&vehicle=Haval
Authorization: Bearer <TOKEN_FROM_INITIAL_REQUEST>
=> HTTP 200 OK
{
users: [
{
id: 'id1',
firstName: 'hashed-value-1',
vehicle: 'Haval'
}, {
id: 'id3',
firstName: 'hashed-value-3',
vehicle: 'Haval'
}
]
}

5. The Border transforms the response from your application backend, replacing hashed
values with clear text and returns the response
=> HTTP 200 OK
{
users: [
{
id: 'id1',
name: 'Liu Lee',
vehicle: 'Haval'
},
{
id: 'id3',
name: 'Liu Chang',
vehicle: 'Haval'
}
]
}

9. File management with REST API services

InCOuntry Border doesn’t work fully support files within your requests, it just proxies them as-is without saving files containing regulated to InCountry DRaaS. If you would like to store files on InCountry DRaaS, you have to use the the file management endpoints available in REST API.

InCountry DRaaS supports the storage of attachments in the following ways:

  1. Database (large object storage)

    1. upload attachments

    2. download attachments

    3. delete attachments

  2. AliCloud OSS

    1. upload attachments

    2. download attachments

    3. update attachments

    4. delete attachments

    5. query attachments

If you are using multipart/form-data format to upload files in your application, you need to switch to our REST API endpoints that use the same format.

note

During uploading of files to InCountry DRaaS, you need to associate them with specific records already stored on InCountry DRaaS. Attachments cannot be imported without a record attribution.

You have to create or import records, which attachments can be further associated with. That’s why we call files – attachments. You can add multiple attachments to one record.

As the format multipart/form-data is the same for you, you just need to switch to the InCountry endpoints for attachments and implement the authorization flow for it. The example of the file upload will be as follows:

Code example

var myHeaders = new Headers();
myHeaders.append("Content-Type", "multipart/form-data");
myHeaders.append("x-filename", "customfilename.txt");
myHeaders.append("Authorization", "Bearer <token>");

var formdata = new FormData();
formdata.append("file", fileInput.files[0], "file.txt");

var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow'
};

fetch(
"https://cn-restapi-mt-01.incountry.io/webapi/records/<record_key>/files",
requestOptions
);

note

Please note that this is an attachment request, which means that a record with the <record_key> field must exist before the files can be attached.

To download the attachment, you can perform the following request:

Code example

var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer <token>");

var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};

fetch(
"https://cn-restapi-mt-01.incountry.io/webapi​/records/<record_key>/files/<file_id>",
requestOptions
);

note

Attachment-based access policy is not supported. We do not regulate access to specific attachments of the record for each user, considering user-specific permissions. But we support the record-based access policy. You can split your attachments by records.

  • If you are using an S3 like API (AWS, Yandex Cloud) and want to store attachments on InCountry DRaaS, you have to migrate to our API, that uses quite a different approach. You will have to implement the following:

1. In your backend, you need to implement an endpoint which internally creates a pre-signed URL using AWS SDK. Then, users requests this endpoint from the browser. The user gets a pre-signed URL from the response:

Code example

REQUEST:
POST https://webapplication.com/api/create-signed-url

HEADERS:
Content-Type: application/json
Authorization: Bearer <token>

BODY: {
"filename": "original_file_name_to_save.txt"
}

RESPONSE:
HTTP/1.1 200 OK
Content-Type: application/json

{
"signedURL": "https://s3.amazonaws.com/demo-bucket/2022/original_file_name_to_save.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA3SGQVQG7FGA6KKA6%2F20221104%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20221104T140227Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=b228dbec8c1008c80c162e1210e4503dceead1e4d4751b4d9787314fd6da4d55",
}

2. Then this URL is used to upload a file:

Code example

var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/octet-stream");
myHeaders.append("Authorization", "Bearer <token>");

var requestOptions = {
method: 'PUT',
headers: myHeaders,
body: fileInput.files[0],
redirect: 'follow'
};

fetch(<signedURL>, requestOptions);

With InCountry DRaaS, you don’t need to create a pre-signed URL first to upload/download an attachment (If you don’t want to use InCountry Alibaba Cloud OSS integration). For basic uploads, you need to construct a multipart/form-data request using the browser HTML forms or using your backend to upload an attachment. Please see the examples above.

10. For dashboard and reports that use aggregated data

A lot of web applications provide reports and dashboards that deal with aggregated data. InCountry DRaaS allows you to calculate aggregated data against regulated values that are stored in InCountry Vault.

Let’s assume you need to display the number of customers whose first name is Liu, and you already have an endpoint for that purpose:

GET https://webapplication.com/getCountCustomersByFirstName?firstName=Liu

firstName is a regulated field and stored in InCountry. For that purpose, you can use the aggregation endpoint from InCountry REST API.

curl --request POST \
--url 'https://cn-restapi-mt-01.incountry.io/webapi/records/aggregate' \
--header 'Authorization: Bearer <ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"next": "ZGluZyBkb25nIGNoaW5nIGNob25n",
"metrics": {
"total_customers": {
"func": "count"
}
},
"filter": {
"key1": "Liu"
},
"options": {
"limit": 100,
"offset": 0
}
}'

You can have several metrics in the request and construct more complex filters. When you query the next batch of groups within the aggregation, you can pass only the next value within the request:

curl --request POST \
--url 'https://cn-restapi-mt-01.incountry.io/webapi/records/aggregate' \
--header 'Authorization: Bearer <ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"next": "ZGluZyBkb25nIGNoaW5nIGNob25n",
}'

11. How to call resident functions against protected data to stay compliant

A common web application uses different validations that check the data format, uniqueness of records, validity of entered values, and so on. InCountry DRaaS provides resident functions that perform remote operations against regulated data and may return either the validation result without exposing actual regulated values or make some data transformations returning the transformed regulated values. In the latter case, you need to call a resident function from the application frontend, as sensitive values should not touch your application backend.

Let’s assume that you already have an existing function within your application at some endpoint that you call from the backend:

curl --request GET \
--url https://webapplication.com/api/customers/<email>/validate \
--header 'Authorization: Bearer <YOUR_SYSTEM_ACCESS_TOKEN>' \

This function performs a simple operation and validates whether the record with a specific email exists or not. In your system, email is regulated data so it's saved to InCountry Vault. Now you need to check whether records with such an email already exist in InCountry Vault or not. You can do this as follows:

  1. Define a base URL to call a resident function that may look like the following

    const restApiUrl = country => `https://${country}-restapi-mt-01.api.incountry.io`;

    where country is a two-character code of the country (ISO format) (for example, us, ar, tr, and so on).

  2. Write a resident function using JavaScript:

    module.exports.handler = async (storage, country, params, modules) => {
    const result = await storage.find(country, { key3: params.email });
    if (result.records.length > 0) {
    return true;
    }
    return false;
    }
  3. Then publish it to InCountry DRaaS. You can do this through InCountry Portal.

    curl --location 'https://<restApiUrl>/serverless/publish' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <INCOUNTRY_ACCESS_TOKEN>' \
    --data '{
    "scriptName": "GET /api/customers/<email>/validate",
    "scriptBody": "module.exports.handler=async(storage,country,params,modules)=>{const result = await storage.find(country,{key3:params.email });if(result.records.length>0){return true;}return false;}",
    "options": {
    "country": "<restApiCountryCode>",
    "forceUpdate": true
    }
    }'

    where restApiCountryCode is a two-character code of the country (ISO format) where you want to save the resident function. To call a resident function with the same HTTP request method and URL path as you do it earlier, you need to provide scriptName in the following format <method> <path_pattern>, for example:

    POST /customServerless/executeByCustomPath/<parameter_1>/<parameter_2>

    where <email> is a parameter.

    One more example of the script name:

    GET /api/customers/<email>/validate

    that can be executed via a request:

    curl --request POST \
    --url https://<restApiUrl>/run/customServerless/executeByCustomPath/<parameter_1>/<parameter_2> \
    --header 'Authorization: Bearer <INCOUNTRY_ACCESS_TOKEN>' \
  4. Execute the function when it is needed in your system by just replacing the original part of the GET request:

    curl --request GET \
    --url https://webapplication.com/api/customers/<email>/validate \
    --header 'Authorization: Bearer <YOUR_SYSTEM_ACCESS_TOKEN>' \

    where <email> equals to the customer’s email you want to validate, as follows:

    curl --request GET \
    --url 'https://<restApiUrl>/run/api/customers/<email>/validate' \
    --header 'Authorization: Bearer <INCOUNTRY_ACCESS_TOKEN>'

    where <restApiUrl> was outputted to you on InCountry Portal.

  5. Use the received result within your application’s business logic.

    {"result": "true"}

    or

    {"result": "false"}

12. Configure outbound email to use redacted email addresses and fields

Your application may send email notifications which may contain PII data such as first name, email, etc. Thanks to our Border, these data will be redacted in your application. To deliver email notifications to the end users with the unredacted data, you should configure an Email Gateway and start sending your email through it.

  1. Create Email Gateway on Portal. Portal will output credentials similar to the ones displayed:

    Email Gateway Login: 41d32e44-XXXX-XXXX-XXXX-c8dd81969221
    Email Gateway Password: LS6D76RCc.X_XX~XXXXVRIvg2j
    Email Gateway: cn-proxy-mt-01.api.incountry.io:587
  2. Let's assume that you store the following record on InCountry DRaaS:

    {
    "record_key":"uFN0UcZ2GeA37hNS",
    "profile_key":"uFN0UcZ2GeA37hNS",
    "body": "{\"name\":\"John Doe\", \"email\": \"john.doe@incountry.com\"}"
    }

    Send a redacted email messages through Email Gateway:

    curl --ssl smtp://cn-proxy-mt-01.api.incountry.io:587 --mail-from no_reply@webapplication.com \
    --mail-rcpt email@pk-email-demo-1.ru --upload-file email.txt \
    --user '41d32e44-XXXX-XXXX-XXXX-c8dd81969221:LS6D76RCc.X_XX~XXXXVRIvg2j'

    Contents of the email.txt file:

    From: no_reply@webapplication.com
    To: email@uFN0UcZ2GeA37hNS.cn
    Subject: Hello, %profile_key=uFN0UcZ2GeA37hNS,name%!
    Date: Thu, 22 Jun 2023 13:45:16

    Dear %profile_key=uFN0UcZ2GeA37hNS,name%,
    We hope that you are happy with using our product!
    We want to notify you that your trial period ends on September 1, 2023.

    When integrating with Email Gateway, you need to insert some placeholders instead of regulated values into your email templates where you want to show unredacted data. For example, email@uFN0UcZ2GeA37hNS.cn will be replaced by Email Gateway with john.doe@incountry.com because Email Gateway will find a record by private_key=uFN0UcZ2GeA37hNS and pick email from the body. And %profile_key=uFN0UcZ2GeA37hNS,name% will be replaced with John Doe because Email Gateway will find a record by private_key=uFN0UcZ2GeA37hNS and pick name from the record body.

13. How to migrate your existing data and tokenize migrated fields within your existing database

Migrate your existing data

Migration of your existing data to InCounty DRaaS is on you. And you can try to solve it with the following recommendations:

  1. You can use our batch write REST API method to bulk import your data;

  2. We have a configuration pack for Pentaho. With the help of it, you can import your data from CSV file and also import files to InCountry DRaaS.

Tokenize migrated fields within your existing database

For that purpose, we have rehashing REST API endpoint. But first you need to migrate these records to InCountry DRaaS and then use the rehashing endpoint, where you should provide record keys and redaction rules for those records. In the response, you will see the redacted records according to provided redaction rules. Then you can update your database with the received redacted records.

note

The rehashing endpoint also needs a deterministic tokenization key (DTK) to be provided. This key is used for redaction algorithms. If you would like from Border to unredact those records, be sure that Border operates with the same DTK.

14. How to migrate configuration of environments (development/testing/production)

info

This functionality is in development and will be available shortly.

InCountry Data Residency-as-a-Service provides different types of environments that you can use for testing and debugging purposes before pushing to production.

How you can utilize this functionality:

  1. Create an environment of the Development or Testing type.

  2. Activate countries and create services.

  3. Implement and integrate data residency services into your application.

  4. Verify the introduced modifications and test them properly.

  5. Create an environment of the Production type.

  6. Activate the same countries and re-create services in this environment.

  7. Export configuration of the environment of the Testing or Development type.

  8. Import configuration of of the environment of the Testing or Development type into the production environment. The InCountry Portal will recreate the following:

    1. data firewall settings

    2. key-alias mappings

    3. Border endpoints

    4. resident functions

  9. Use some DevOps utility for continuous deployment of changed environment configuration.