클라이언트 측 필드 레벨 암호화 - Amazon DocumentDB

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

클라이언트 측 필드 레벨 암호화

Amazon DocumentDB 클라이언트 측 필드 레벨 암호화(FLE)를 사용하면 Amazon DocumentDB 클러스터로 전송하기 전에 클라이언트 애플리케이션의 민감한 데이터를 암호화할 수 있습니다. 민감한 데이터는 클러스터에서 저장 및 처리될 때 암호화된 상태로 유지되며 검색 시 클라이언트 애플리케이션에서 복호화됩니다.

시작하기

Amazon DocumentDB에서 클라이언트측 FLE의 초기 구성은 암호화 키 생성, 애플리케이션에 역할 연결, 애플리케이션 구성, 암호화 옵션을 통한 CRUD 작업 정의 등을 포함하는 4단계 프로세스입니다.

1단계: 암호화 키 생성하기

AWS Key Management Service을 사용하여 민감한 데이터 필드를 암호화하고 해독하는 데 사용되는 대칭 키를 생성하고 필요한 IAM 사용 권한을 제공합니다. AWS KMS는 데이터 키(DK)를 암호화하는 데 사용되는 고객 키(CK)를 저장합니다. 보안 태세를 강화하려면 고객 키를 KMS에 저장하는 것이 좋습니다. 데이터 키는 Amazon DocumentDB 컬렉션에 저장되는 보조 키로, 문서를 Amazon DocumentDB에 저장하기 전에 민감한 필드를 암호화하는 데 필요합니다. 고객 키는 데이터 키를 암호화하고, 데이터 키는 다시 데이터를 암호화하고 복호화합니다. 글로벌 클러스터를 사용하는 경우 여러 리전의 다양한 서비스 역할이 사용할 수 있는 다중 리전 키를 만들 수 있습니다.

키를 생성하는 방법을 포함하여 AWS Key Management Service에 대한 자세한 내용은 AWS키 관리 서비스 개발자 가이드를 참조하십시오.

2단계: 역할을 애플리케이션에 연결하기

적절한 AWS KMS 권한을 가진 IAM 정책을 생성합니다. 이 정책은 연결되는 IAM 자격 증명이 리소스 필드에 지정된 KMS 키를 암호화하고 해독하도록 허용합니다. 애플리케이션은 AWS KMS로 인증하기 위해 이 IAM 역할을 가정합니다.

정책은 다음과 비슷할 것입니다.

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

3단계: 애플리케이션 구성

지금까지 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 } }
  2. 데이터 키를 암호화하는 데 사용되는 고객 키를 지정합니다.

    customer_key = { “region”: “AWS region of the customer_key”, “key”: “customer_key ARN” } key_vault_namespace = "encryption.dataKeys" key_alt_name = 'TEST_DATA_KEY'
  3. 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 )
  4. 데이터 키를 생성합니다.

    data_key_id = client_encryption.create_data_key(provider, customer_key, key_alt_name = [key_alt_name])
  5. 기존 데이터 키를 검색합니다.

    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 작업 정의하기

암호화 옵션을 사용하여 CRUD 작업을 정의합니다.

  1. 단일 문서를 작성/읽기/삭제할 컬렉션을 정의합니다.

    coll = client.gameinfo.users
  2. 명시적 암호화 - 필드를 암호화하고 다음을 삽입합니다.

    참고

    “key_id” 또는 “key_alt_name” 중 정확히 하나를 입력해야 합니다.

    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"] })

예: 클라이언트 측 필드 수준 암호화 구성 파일

다음은 자신의 정보를 각각의 사용자 입력 자리 표시자로 변경하는 예제입니다.

# 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의 쿼리

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을 각 문서에 저장된 암호화된 필드 값과 비교합니다. 복호화된 데이터와 값을 사용하여 찾기 작업의 불평등 검사를 수행하면 결과가 성공적으로 생성되더라도 다른 결과가 반환될 수 있습니다.

제한 사항

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는 몽고 쉘의 명시적인 클라이언트 측 FLE를 지원하지 않습니다. 하지만 이 기능은 지원되는 모든 드라이버에서 사용할 수 있습니다.