Recently can often hear a certain company user information was leaked, a certain company user opened a room record was taken off pants… Data privacy is the lifeblood of the enterprise, and I don’t think I need to say much about its importance.

In the last article, we introduced AWS KMS service: What Why and How? A brief review: KMS is called Key Management Service, also known as a Key Management system. It is designed to fundamentally solve the problem of data security. At the same time, it also has a complete security audit function, so that I can see at a glance who can access my data and who touched my data when.

With the help of KMS, we were able to do this so that even if I got my pants ripped off, the attacker could not decrypt my data! In this article, we will take a concrete look at how KMS can be put into practice to improve product security.

Here we classify products into two categories:

  1. General products: need to protect their own data, such as various self-operated e-commerce platforms.
  2. Platform products: Platform service providers need to protect tenant data, such as Authing and Youzan.

The reason for this distinction is that platform service providers are multi-tenant scenarios. For a generic type of product, you just need to encrypt the data, and for a platform type of product, ideally, tenants want to do two things:

1. Know when and for what reason the platform service providers access my data. 2. When I no longer use your service, I can cancel the data authorization of the service provider of the platform with one click, and the service provider of the platform can no longer access my data in the future.

In this case, the KMS cross-account authorization function can be used. The basic process is as follows: The tenant creates a key in the AWS KMS background and authorizes it to the platform service provider. The platform service provider uses this key to encrypt/decrypt the tenant’s data. With the help of AWS Cloud Trail, the tenant can easily know when and for what reason the platform service provider accesses my data. When a tenant decides not to use a platform service provider’s product, it only needs to cancel its authorization in the AWS KMS background.

The basic principle is so simple, from the technical point of view, the following combs several technical problems that need to be solved:

  1. How to use KMS to encrypt/decrypt data?
  2. How do I authorize the KMS key to another account?
  3. How do I use Cloud Trail to see when a third party has access to my data?
  4. As a platform service provider, how to solve the binding problem of KMS service provider?
  5. The final point is the difficult one: how do you automatically encrypt and decrypt data without drastically changing the business logic?

Let’s take a step-by-step look at how to apply KMS to your product.

1. Enable the KMS service and create a KMS CKM

First you need to have an AWS account. Create a User (or Role) with full KMS permissions. The User inherits the following Policy:

{
    "Version": "2012-10-17"."Statement": [{"Sid": "VisualEditor0"."Effect": "Allow"."Action": "kms:*"."Resource": "*"}}]Copy the code

Once you have created the User, you should be able to get the accessKeyId and secretAccessKey for that User, which will be used later in the SDK.

Then on the AWS Console KMS management page, create a Custom Managed Key and set the Key manager and IAM users and roles that can use CMK in encryption operations to the User created in the previous step. After creation you can get the KeyId of the key:

2. KMS encrypts and decrypts Demo

We usually use AWS Encryption SDK to encrypt and decrypt data. It saves us a lot of work and comes with a lot of best practices, such as using envelope Encryption, kerying, etc.

AWS Encryption SDK supports a variety of languages, such as Java, Python, C, and JavaScript. Here we use JavaScript as an example. Encryption Demo:

import * as AWS from "aws-sdk"
import { KmsKeyringNode, encrypt, decrypt, getClient, MessageHeader } from '@aws-crypto/client-node'

 const keyring = new KmsKeyringNode({
  generatorKeyId: "Here's your KeyId.",
  clientProvider: getClient(AWS.KMS, {
      credentials: {
        accessKeyId: config.accessKeyId,
        secretAccessKey: config.secretAccessKey,
      }
    })
 })
 const { result } = await encrypt(keyring, "Contents that need to be encrypted", { encryptionContext: {
    key: "Additional context Information"}})Copy the code

Note the following points:

  1. GeneratorKeyId is the CMK key ID
  2. I’m initializing a keyRing here.
  3. EncryptionContext is optional encryptionContext information that can be seen on the Cloud Trail audit page.

Decrypt the Demo:

import * as AWS from "aws-sdk"
import { KmsKeyringNode, encrypt, decrypt, getClient, MessageHeader } from '@aws-crypto/client-node'

 const keyring = new KmsKeyringNode({
  generatorKeyId: "Your KeyId",
  clientProvider: getClient(AWS.KMS, {
      credentials: {
        accessKeyId: config.accessKeyId,
        secretAccessKey: config.secretAccessKey,
      }
    })
 })
const { plaintext, messageHeader } = await decrypt(keyring, encryptedData)
Copy the code

3. How to authorize the key to other AWS accounts

When creating the CMK Define Key Permission step, you can specify the AWS account of the third party to be authorized and enter the AWS account ID of the third party.

Licensees can use this CMK as follows:

  1. Create a User with all CKM operation permissions
  2. The user inherits the following policies: a. Resource is the ARN of CMK
{
  "Version": "2012-10-17"."Statement": [{"Sid": "Allow Use Of CMK In External Account"."Effect": "Allow"."Action": [
        "kms:Encrypt"."kms:Decrypt"."kms:ReEncrypt*"."kms:GenerateDataKey*"."kms:DescribeKey"]."Resource": "arn:aws:kms:ap-northeast-1:xxxxxxxxx:key/b09ea52c-7262-4e60-b775-xxxxxx"}}]Copy the code
  1. Use CMK to encrypt and decrypt data with SDK.
  2. When the authorized party no longer wants the authorized party to use the CMK, the authorized party’s account ID is removed from the key management page.

4. Use Cloud Trail to view key audit

Create a Trail:

By default, all subsequent uses of your key will appear in the Event History:

As shown in the figure above, you can see the Decrypt record with the request details:

  • UserIdentity is the authorized party.

5. As a platform service provider, how to solve the binding problem of KMS service provider

The common KMS service providers in the market are as follows:

  • AWS KMS
  • Ali cloud KMS
  • Tencent cloud KMS

As a platform service provider, it is better for us to provide tenants with the right to choose KMS service providers. However, different KMS service providers have different usage methods, so we need to do the code level encapsulation, for example, we can set four modules KMS, Aliyun, AWS and Tecent. Expose the encrypt and decrypt methods in the KMS module and call the actual methods according to the KMS service provider configured by the tenant.

6. How to encrypt and decrypt data without changing the existing code

If the previous code design is not good enough, there will be a lot of modifications to the existing query, insert business code, this cost is very large. So we need to think about other solutions:

  1. Subscribe to database logs, i.e. MySQL binlog, PostgreSQL Write-Ahead Logging (WAL), mongodb Change Streams.
  2. Database ORM hooks, such as TypeOrm Entity Listeners and Subscribers and Mongoose Middlewares, are used to encrypt data before insertion and decrypt data after reading.

Here is a sample mongoose code:

schema.post(['find'.'findOne'], async function (docs, next) {
  if(! Array.isArray(docs)) { docs = [docs]; }for (letDoc of docs) {// Decrypt data} next()}) schema.pre('findOneAndUpdate', async function(next) {// Encrypt data}) schema.post('findOneAndUpdate', async function(doc, next) {// Decrypt the data})Copy the code

conclusion

We all need to be responsible for users’ data, especially platform service providers. At present, KMS is a good choice.