Python 데이터 키 캐싱 예제 - AWS 암호화 SDK

Python 데이터 키 캐싱 예제

이 코드는 Python용 local cache를 사용하여 기본적인 데이터 키 캐싱 구현을 만듭니다. AWS 암호화 SDK의 Python 구현에 대한 자세한 내용은 Python용 AWS 암호화 SDK 단원을 참조하십시오.

이 코드는 local cache의 인스턴스 두 개를 만듭니다. 하나는 데이터를 암호화하는 데이터 생산자용 인스턴스이고, 다른 하나는 데이터를 해독하는 소비자(Lambda 함수)용 인스턴스입니다. 자세한 구현 방법은 AWS 암호화 SDK용 Python 설명서를 참조하십시오.

데이터 키 캐싱의 기본 요소에 초점을 맞춘 간단한 예제를 보려면 데이터 키 캐싱을 사용하여 메시지 암호화 단원을 참조하십시오.

생산자

생산자는 맵을 받아 JSON으로 변환하고 AWS 암호화 SDK를 사용하여 암호화한 후, 각 AWS 리전의 Kinesis 스트림에 암호화 텍스트 레코드를 푸시합니다.

이 코드는 암호화 자료 관리자 캐싱(CMM 캐싱)를 정의하고 local cache 및 기본 AWS KMS 마스터 키 공급자와 연결합니다. CMM 캐싱은 의 데이터 키(및 관련 암호화 자료)를 캐싱합니다. 또한 SDK를 대신하여 캐시와 상호 작용하고 사용자가 설정한 보안 임계값을 적용합니다.

encrypt 메서드를 호출하면 일반 암호화 자료 관리자(CMM) 또는 대신에 CMM 캐싱이 지정되므로, 이 메서드에는 데이터 키 캐싱이 사용됩니다.

""" Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at https://aws.amazon.com/apache-2-0/ or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ import json import uuid from aws_encryption_sdk import encrypt, KMSMasterKeyProvider, CachingCryptoMaterialsManager, LocalCryptoMaterialsCache from aws_encryption_sdk.key_providers.kms import KMSMasterKey import boto3 class MultiRegionRecordPusher(object): """Pushes data to Kinesis Streams in multiple Regions.""" CACHE_CAPACITY = 100 MAX_ENTRY_AGE_SECONDS = 300.0 MAX_ENTRY_MESSAGES_ENCRYPTED = 100 def __init__(self, regions, kms_alias_name, stream_name): self._kinesis_clients = [] self._stream_name = stream_name # Set up KMSMasterKeyProvider with cache _key_provider = KMSMasterKeyProvider() # Add MasterKey and Kinesis client for each Region for region in regions: self._kinesis_clients.append(boto3.client('kinesis', region_name=region)) regional_master_key = KMSMasterKey( client=boto3.client('kms', region_name=region), key_id=kms_alias_name ) _key_provider.add_master_key_provider(regional_master_key) cache = LocalCryptoMaterialsCache(capacity=self.CACHE_CAPACITY) self._materials_manager = CachingCryptoMaterialsManager( master_key_provider=_key_provider, cache=cache, max_age=self.MAX_ENTRY_AGE_SECONDS, max_messages_encrypted=self.MAX_ENTRY_MESSAGES_ENCRYPTED ) def put_record(self, record_data): """JSON serializes and encrypts the received record data and pushes it to all target streams. :param dict record_data: Data to write to stream """ # Kinesis partition key to randomize write load across stream shards partition_key = uuid.uuid4().hex encryption_context = {'stream': self._stream_name} # JSON serialize data json_data = json.dumps(record_data) # Encrypt data encrypted_data, _header = encrypt( source=json_data, materials_manager=self._materials_manager, encryption_context=encryption_context ) # Put records to Kinesis stream in all Regions for client in self._kinesis_clients: client.put_record( StreamName=self._stream_name, Data=encrypted_data, PartitionKey=partition_key )

소비자

데이터 소비자는 Kinesis 이벤트에 의해 트리거되는 AWS Lambda 함수입니다. 각 레코드를 해독하고 역직렬화하며 일반 텍스트 레코드를 동일 리전의 DynamoDB 테이블에 씁니다.

생산자 코드와 마찬가지로, 소비자 코드도 decrypt 메서드 호출에서 암호화 자료 관리자 캐싱(CMM 캐싱)를 사용하여 데이터 키 캐싱을 활성화합니다.

""" Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at https://aws.amazon.com/apache-2-0/ or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ import base64 import json import logging import os from aws_encryption_sdk import decrypt, KMSMasterKeyProvider, CachingCryptoMaterialsManager, LocalCryptoMaterialsCache import boto3 _LOGGER = logging.getLogger(__name__) _is_setup = False CACHE_CAPACITY = 100 MAX_ENTRY_AGE_SECONDS = 600.0 def setup(): """Sets up clients that should persist across Lambda invocations.""" global materials_manager key_provider = KMSMasterKeyProvider() cache = LocalCryptoMaterialsCache(capacity=CACHE_CAPACITY) # Because the cache is used only for decryption, the code doesn't set # the max bytes or max message security thresholds that are enforced # only on on data keys used for encryption. materials_manager = CachingCryptoMaterialsManager( master_key_provider=key_provider, cache=cache, max_age=MAX_ENTRY_AGE_SECONDS ) global table table_name = os.environ.get('TABLE_NAME') table = boto3.resource('dynamodb').Table(table_name) global _is_setup _is_setup = True def lambda_handler(event, context): """Decrypts all incoming Kinesis records and writes records to DynamoDB.""" _LOGGER.debug('New event:') _LOGGER.debug(event) if not _is_setup: setup() with table.batch_writer() as batch: for record in event.get('Records', []): # Record data base64-encoded by Kinesis ciphertext = base64.b64decode(record['kinesis']['data']) # Decrypt and unpack record plaintext, header = decrypt( source=ciphertext, materials_manager=materials_manager ) item = json.loads(plaintext) # Verify the encryption context value stream_name = record['eventSourceARN'].split('/', 1)[1] if stream_name != header.encryption_context['stream']: raise ValueError('Wrong Encryption Context!') # Write record to DynamoDB batch.put_item(Item=item)