

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# クライアント側のフィールドレベルの暗号化
<a name="field-level-encryption"></a>

Amazon DocumentDB のクライアント側のフィールドレベル暗号化 (FLE) を使用すると、Amazon DocumentDB クラスターに転送される前に、クライアントアプリケーションの機密データを暗号化できます。機密データは、クラスターで保存および処理されるときは暗号化されたままで、取得時にはクライアントアプリケーションで復号化されます。

**Topics**
+ [はじめに](#fle-getting-started)
+ [クライアント側 FLE でのクエリ](#fle-querying)
+ [制限](#fle-limitationa)

## はじめに
<a name="fle-getting-started"></a>

Amazon DocumentDB でのクライアント側 FLE の初期設定は、暗号化キーの作成、アプリケーションへのロールの関連付け、アプリケーションの設定、暗号化オプションによる CRUD オペレーションの定義を含む 4 ステップのプロセスです。

**Topics**
+ [ステップ 1: 暗号化キーの作成](#fle-step-create-key)
+ [ステップ 2: ロールとアプリケーションの関連付け](#fle-step-associate-role)
+ [ステップ 3: アプリケーションの設定](#fle-step-config-app)
+ [ステップ 4: CRUD オペレーションの定義](#fle-step-crud-ops)
+ [例:クライアント側のフィールドレベル暗号化設定ファイル](#fle-config-example)

### ステップ 1: 暗号化キーの作成
<a name="fle-step-create-key"></a>

AWS Key Management Service を使用して、機密データフィールドの暗号化と復号化に使用する対称キーを作成し、必要な IAM 使用権限を付与します。 AWS KMS は、データキー (DK) の暗号化に使用されるカスタマーキー (CK) を格納します。セキュリティ体制を強化するため、カスタマーキーは KMS に保存することをお勧めします。データキーは Amazon DocumentDB コレクションに保存されるセカンダリキーで、Amazon DocumentDB にドキュメントを保存する前に機密フィールドを暗号化するために必要です。カスタマーキーはデータキーを暗号化し、データキーはデータを暗号化および復号化します。グローバルクラスターを使用している場合は、さまざまなリージョンのさまざまなサービスロールで使用できるマルチリージョンキーを作成できます。

キーの作成方法など、AWS Key Management Service の詳細については、「[AWSKey Management Service デベロッパーガイド](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html)」を参照してください。

### ステップ 2: ロールとアプリケーションの関連付け
<a name="fle-step-associate-role"></a>

適切な AWS KMS 許可を持つ IAM ポリシーを作成します。このポリシーは、アタッチされた IAM アイデンティティで、リソースフィールドで指定された KMS キーの暗号化と復号化ができるようにします。アプリケーションはこの IAM ロールを引き受けて AWS KMS の認証を行います。

ポリシーは次のようになります。

```
{ "Effect": "Allow",
"Action": ["kms:Decrypt", "kms:Encrypt"],
"Resource": "Customer Key ARN"
}
```

### ステップ 3: アプリケーションの設定
<a name="fle-step-config-app"></a>

これまでに、AWS KMS でカスタマーキーを定義し、IAM ロールを作成し、そのロールにカスタマーキーにアクセスするための適切な IAM アクセス許可を付与しました。必要なパッケージをインポートします。

```
import boto3
import json
import base64
from pymongo import MongoClient
from pymongo.encryption import (Algorithm,
                                ClientEncryption)
```

```
# create a session object: 
my_session = boto3.session.Session()

# get access_key and secret_key programmatically using get_frozen_credentials() method:
 current_credentials = my_session.get_credentials().get_frozen_credentials()
```

1. KMS プロバイダーのタイプに「aws」を指定し、前のステップで取得したアカウント認証情報を入力します。

   ```
   provider = "aws"
   kms_providers = {
       provider: {
           "accessKeyId": current_credentials.access_key,
           "secretAccessKey": current_credentials.secret_key
       }
   }
   ```

1. データキーの暗号化に使用するカスタマーキーを指定します。

   ```
   customer_key = {
   “region”: “AWS region of the customer_key”,
       “key”: “customer_key ARN”
   }
   
   key_vault_namespace = "encryption.dataKeys"
   
   key_alt_name = 'TEST_DATA_KEY'
   ```

1. MongoClient オブジェクトを設定します。

   ```
   client = MongoClient(connection_string)
   
   coll = client.test.coll
   coll.drop()
   
   client_encryption = ClientEncryption(
       kms_providers, # pass in the kms_providers variable from the previous step
       key_vault_namespace = key_vault_namespace,
       client,
       coll.codec_options
   )
   ```

1. データキーを生成します。

   ```
   data_key_id = client_encryption.create_data_key(provider,
       customer_key,
       key_alt_name = [key_alt_name])
   ```

1. 既存のデータキーを取得します。

   ```
   data_key = DataKey("aws",
       master_key = customer_key)
   key_id = data_key["_id"]
   data_key_id = client[key_vault_namespace].find_one({"_id": key_id})
   ```

### ステップ 4: CRUD オペレーションの定義
<a name="fle-step-crud-ops"></a>

CRUD オペレーションを暗号化オプションで定義します。

1. 1 つのドキュメントの書き込み/読み取り/削除を行うコレクションを定義します。

   ```
   coll = client.gameinfo.users
   ```

1. 明示的な暗号化 - フィールドを暗号化して以下を挿入します。
**注記**  
「key\$1id」または「key\$1alt\$1name」の 1 つを正確に指定する必要があります。

   ```
   encrypted_first_name = client_encryption.encrypt(
       "Jane",
       Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
       key_alt_name=data_key_id
   )
   encrypted_last_name = client_encryption.encrypt(
       "Doe",
       Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
       key_alt_name=data_key_id
   )
   encrypted_dob = client_encryption.encrypt(
       "1990-01-01",
       Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random,
       key_alt_name=data_key_id
   )
   
   coll.insert_one(
       {"gamerTag": "jane_doe90",
       "firstName": encrypted_first_name,
       "lastName": encrypted_last_name,
       "dateOfBirth":encrypted_dob,
       "Favorite_games":["Halo","Age of Empires 2","Medal of Honor"]
   })
   ```

### 例:クライアント側のフィールドレベル暗号化設定ファイル
<a name="fle-config-example"></a>

次の例では、各 *ユーザー入力プレースホルダー* を独自の情報に置き換えます。

```
# import python packages:
import boto3
import json
import base64
from pymongo import MongoClient
from pymongo.encryption import (Algorithm,
                                ClientEncryption)

def main():
    
    # create a session object:
    my_session = boto3.session.Session()
    
    # get aws_region from session object:
    aws_region = my_session.region_name
    
    # get access_key and secret_key programmatically using get_frozen_credentials() method:
    current_credentials = my_session.get_credentials().get_frozen_credentials()
    provider = "aws"
    
    # define the kms_providers which is later used to create the Data Key:
    kms_providers = {
        provider: {
            "accessKeyId": current_credentials.access_key,
            "secretAccessKey": current_credentials.secret_key
        }
    }
    
    # enter the kms key ARN. Replace the example ARN value.
    kms_arn = "arn:aws:kms:us-east-1:123456789:key/abcd-efgh-ijkl-mnop"
    customer_key = {
        "region": aws_region,
        "key":kms_arn
    }

    # secrets manager is used to strore and retrieve user credentials for connecting to an Amazon DocumentDB cluster. 
    # retrieve the secret using the secret name. Replace the example secret key.
    secret_name = "/dev/secretKey"
    docdb_credentials = json.loads(my_session.client(service_name = 'secretsmanager', region_name = "us-east-1").get_secret_value(SecretId = secret_name)['SecretString'])

    connection_params = '/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'
    conn_str = 'mongodb://' + docdb_credentials["username"] + ':' + docdb_credentials["password"] + '@' + docdb_credentials["host"] + ':' + str(docdb_credentials["port"]) + connection_params
    client = MongoClient(conn_str) 

    coll = client.test.coll
    coll.drop()
    
    # store the encryption data keys in a key vault collection (having naming convention as db.collection):
    key_vault_namespace = "encryption.dataKeys"
    key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)

    # set up the key vault (key_vault_namespace) for this example:
    key_vault = client[key_vault_db_name][key_vault_coll_name]
    key_vault.drop()
    key_vault.create_index("keyAltNames", unique=True)

    client_encryption = ClientEncryption(
        kms_providers,
        key_vault_namespace,
        client,
        coll.codec_options)
    
    # create a new data key for the encrypted field:
    data_key_id = client_encryption.create_data_key(provider, master_key=customer_key, key_alt_names=["some_key_alt_name"], key_material = None)
    
    # explicitly encrypt a field:
    encrypted_first_name = client_encryption.encrypt(
    "Jane",
    Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
    key_id=data_key_id
    )
    coll.insert_one(
    {"gamerTag": "jane_doe90",
    "firstName": encrypted_first_name
    })
    doc = coll.find_one()
    print('Encrypted document: %s' % (doc,))
    
    # explicitly decrypt the field:
    doc["encryptedField"] = client_encryption.decrypt(doc["encryptedField"])
    print('Decrypted document: %s' % (doc,))
    
    # cleanup resources:
    client_encryption.close()
    client.close()
    
    if __name__ == "__main__":
        main()
```

## クライアント側 FLE でのクエリ
<a name="fle-querying"></a>

Amazon DocumentDB は、クライアント側 FLE によるポイント等式クエリをサポートしています。不等式クエリや比較クエリは、不正確な結果を返す可能性があります。読み取りオペレーションと書き込みオペレーションは、復号化された値に対して同じオペレーションを実行する場合と比較して、予期しない動作や誤った動作をする可能性があります。

たとえば、ゲーマースコアが 500 を超えるドキュメントのフィルターをクエリするには:

```
db.users.find( {
    "gamerscore" : { $gt : 500 }
})
```

クライアントは明示的な暗号化の方法を使用してクエリ値を暗号化します。

```
encrypted_gamerscore_filter = client_encryption.encrypt(
    500,
        Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
        key_alt_name=data_key_id
        )

db.users.find( {
    "gamerscore" : { $gt : encrypted_gamerscore_filter }
} )
```

検索オペレーションでは、Amazon DocumentDB は、暗号化された値 500 と各ドキュメントに保存されている暗号化されたフィールド値を不等号チェックを使用して比較します。検索オペレーションの不等式チェックは、復号化されたデータと値を使用して実行すると、結果の生成に成功しても、異なる結果が返されることがあります。

## 制限
<a name="fle-limitationa"></a>

Amazon DocumentDB のクライアント側のフィールドレベル暗号化には、以下の制限が適用されます。
+ Amazon DocumentDB がサポートするのは、ポイント等式クエリのみです。不等式クエリや比較クエリは、不正確な結果を返す可能性があります。読み取りオペレーションと書き込みオペレーションは、復号化された値に対して同じオペレーションを実行する場合と比較して、予期しない動作や誤った動作をする可能性があります。ゲーマースコアが 500 を超えるドキュメントのフィルターをクエリするには、

  ```
  db.users.find( {
      "gamerscore" : { $gt : 500 }
      })
  ```

  クライアントは明示的な暗号化の方法を使用してクエリ値を暗号化します。

  ```
  encrypted_gamerscore_filter = client_encryption.encrypt(
      500,
      Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
      key_alt_name=data_key_id
  )
  
  db.users.find({
      "gamerscore" : { $gt : encrypted_gamerscore_filter }
  })
  ```

  検索オペレーションでは、Amazon DocumentDB は、暗号化された値 500 と各ドキュメントに保存されている暗号化されたフィールド値を不等号チェックを使用して比較します。検索オペレーションの不等式チェックは、復号化されたデータと値を使用して実行すると、結果の生成に成功しても、異なる結果が返されることがあります。
+ Amazon DocumentDB は、Mongo Shell からの明示的なクライアント側 FLE をサポートしていません。ただし、この機能はサポートされているどのドライバーでも動作します。