Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Exemple de code de mise en cache des clés de données
Cet exemple de code crée une implémentation simple de la mise en cache des clés de données avec un cache local en Java et Python. Le code crée deux instances d'un cache local : l'une pour les producteurs de données qui chiffrent les données et l'autre pour les consommateurs de données (AWS Lambda fonctions) qui les déchiffrent. Pour plus de détails sur l'implémentation de la mise en cache des clés de données dans chaque langage, consultez la documentation Javadoc et Python du. AWS Encryption SDK
La mise en cache des clés de données est disponible pour tous les langages de programmation pris en AWS Encryption SDK charge.
Pour des exemples complets et testés d'utilisation de la mise en cache des clés de données dans le AWS Encryption SDK, voir :
Producer
Le producteur obtient une carte, la convertit, l'utilise AWS Encryption SDK pour JSON la chiffrer et envoie l'enregistrement de texte chiffré vers un flux Kinesis dans chacune d'elles. Région AWS
Le code définit un gestionnaire de matériel cryptographique de mise en cache (mise en cacheCMM) et l'associe à un cache local et à un fournisseur de clé AWS KMS principale sous-jacent. La mise en cache CMM met en cache les clés de données (et le matériel cryptographique associé) provenant du fournisseur de clé principale. Il interagit également avec le cache au nom de SDK et applique les seuils de sécurité que vous avez définis.
Étant donné que l'appel à la méthode de chiffrement spécifie une mise en cacheCMM, au lieu d'un gestionnaire de matériel cryptographique (CMM) ou d'un fournisseur de clé principale standard, le chiffrement utilisera la mise en cache de clés de données.
- Java
-
L'exemple suivant utilise la version 2. x du Kit SDK de chiffrement AWS pour Java. Version 3. x de Kit SDK de chiffrement AWS pour Java déconseille la mise en cache des clés de données. CMM Avec la version 3. x, vous pouvez également utiliser le trousseau de clés AWS KMS hiérarchique, une solution alternative de mise en cache des matériaux cryptographiques.
/*
* 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
*
* http://aws.amazon.com/apache2.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.
*/
package com.amazonaws.crypto.examples.kinesisdatakeycaching;
import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.MasterKeyProvider;
import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager;
import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider;
import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory;
import com.amazonaws.util.json.Jackson;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisClient;
import software.amazon.awssdk.services.kms.KmsClient;
/**
* Pushes data to Kinesis Streams in multiple Regions.
*/
public class MultiRegionRecordPusher {
private static final long MAX_ENTRY_AGE_MILLISECONDS = 300000;
private static final long MAX_ENTRY_USES = 100;
private static final int MAX_CACHE_ENTRIES = 100;
private final String streamName_;
private final ArrayList<KinesisClient> kinesisClients_;
private final CachingCryptoMaterialsManager cachingMaterialsManager_;
private final AwsCrypto crypto_;
/**
* Creates an instance of this object with Kinesis clients for all target Regions and a cached
* key provider containing KMS master keys in all target Regions.
*/
public MultiRegionRecordPusher(final Region[] regions, final String kmsAliasName,
final String streamName) {
streamName_ = streamName;
crypto_ = AwsCrypto.builder()
.withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
.build();
kinesisClients_ = new ArrayList<>();
AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.builder().build();
// Build KmsMasterKey and AmazonKinesisClient objects for each target region
List<KmsMasterKey> masterKeys = new ArrayList<>();
for (Region region : regions) {
kinesisClients_.add(KinesisClient.builder()
.credentialsProvider(credentialsProvider)
.region(region)
.build());
KmsMasterKey regionMasterKey = KmsMasterKeyProvider.builder()
.defaultRegion(region)
.builderSupplier(() -> KmsClient.builder().credentialsProvider(credentialsProvider))
.buildStrict(kmsAliasName)
.getMasterKey(kmsAliasName);
masterKeys.add(regionMasterKey);
}
// Collect KmsMasterKey objects into single provider and add cache
MasterKeyProvider<?> masterKeyProvider = MultipleProviderFactory.buildMultiProvider(
KmsMasterKey.class,
masterKeys
);
cachingMaterialsManager_ = CachingCryptoMaterialsManager.newBuilder()
.withMasterKeyProvider(masterKeyProvider)
.withCache(new LocalCryptoMaterialsCache(MAX_CACHE_ENTRIES))
.withMaxAge(MAX_ENTRY_AGE_MILLISECONDS, TimeUnit.MILLISECONDS)
.withMessageUseLimit(MAX_ENTRY_USES)
.build();
}
/**
* JSON serializes and encrypts the received record data and pushes it to all target streams.
*/
public void putRecord(final Map<Object, Object> data) {
String partitionKey = UUID.randomUUID().toString();
Map<String, String> encryptionContext = new HashMap<>();
encryptionContext.put("stream", streamName_);
// JSON serialize data
String jsonData = Jackson.toJsonString(data);
// Encrypt data
CryptoResult<byte[], ?> result = crypto_.encryptData(
cachingMaterialsManager_,
jsonData.getBytes(),
encryptionContext
);
byte[] encryptedData = result.getResult();
// Put records to Kinesis stream in all Regions
for (KinesisClient regionalKinesisClient : kinesisClients_) {
regionalKinesisClient.putRecord(builder ->
builder.streamName(streamName_)
.data(SdkBytes.fromByteArray(encryptedData))
.partitionKey(partitionKey));
}
}
}
- Python
-
"""
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 EncryptionSDKClient, StrictAwsKmsMasterKeyProvider, CachingCryptoMaterialsManager, LocalCryptoMaterialsCache, CommitmentPolicy
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 EncryptionSDKClient
_client = EncryptionSDKClient(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
# Set up KMSMasterKeyProvider with cache
_key_provider = StrictAwsKmsMasterKeyProvider(kms_alias_name)
# 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 = _client.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
)
Consommateur
Le consommateur de données est une AWS Lambdafonction déclenchée par des événements Kinesis. Il déchiffre et désérialise chaque enregistrement, puis écrit l'enregistrement en texte brut dans une table Amazon DynamoDB de la même région.
À l'instar du code producteur, le code consommateur permet la mise en cache des clés de données en utilisant un gestionnaire de matériel cryptographique de mise en cache (mise en cacheCMM) dans les appels à la méthode de déchiffrement.
Le code Java crée un fournisseur de clé principale en mode strict avec une valeur spécifiée AWS KMS key. Le mode strict n'est pas obligatoire lors du déchiffrement, mais il s'agit d'une bonne pratique. Le code Python utilise le mode découverte, qui permet d' AWS Encryption SDK utiliser n'importe quelle clé d'encapsulation qui a chiffré une clé de données pour la déchiffrer.
- Java
-
L'exemple suivant utilise la version 2. x du Kit SDK de chiffrement AWS pour Java. Version 3. x de Kit SDK de chiffrement AWS pour Java déconseille la mise en cache des clés de données. CMM Avec la version 3. x, vous pouvez également utiliser le trousseau de clés AWS KMS hiérarchique, une solution alternative de mise en cache des matériaux cryptographiques.
Ce code crée un fournisseur de clé principale pour le déchiffrement en mode strict. Ils ne AWS Encryption SDK
peuvent utiliser que celui que AWS KMS keys vous spécifiez pour déchiffrer votre message.
/*
* 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
*
* http://aws.amazon.com/apache2.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.
*/
package com.amazonaws.crypto.examples.kinesisdatakeycaching;
import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager;
import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord;
import com.amazonaws.util.BinaryUtils;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
/**
* Decrypts all incoming Kinesis records and writes records to DynamoDB.
*/
public class LambdaDecryptAndWrite {
private static final long MAX_ENTRY_AGE_MILLISECONDS = 600000;
private static final int MAX_CACHE_ENTRIES = 100;
private final CachingCryptoMaterialsManager cachingMaterialsManager_;
private final AwsCrypto crypto_;
private final DynamoDbTable<Item> table_;
/**
* 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.
*/
public LambdaDecryptAndWrite() {
String kmsKeyArn = System.getenv("CMK_ARN");
cachingMaterialsManager_ = CachingCryptoMaterialsManager.newBuilder()
.withMasterKeyProvider(KmsMasterKeyProvider.builder().buildStrict(kmsKeyArn))
.withCache(new LocalCryptoMaterialsCache(MAX_CACHE_ENTRIES))
.withMaxAge(MAX_ENTRY_AGE_MILLISECONDS, TimeUnit.MILLISECONDS)
.build();
crypto_ = AwsCrypto.builder()
.withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
.build();
String tableName = System.getenv("TABLE_NAME");
DynamoDbEnhancedClient dynamodb = DynamoDbEnhancedClient.builder().build();
table_ = dynamodb.table(tableName, TableSchema.fromClass(Item.class));
}
/**
* @param event
* @param context
*/
public void handleRequest(KinesisEvent event, Context context)
throws UnsupportedEncodingException {
for (KinesisEventRecord record : event.getRecords()) {
ByteBuffer ciphertextBuffer = record.getKinesis().getData();
byte[] ciphertext = BinaryUtils.copyAllBytesFrom(ciphertextBuffer);
// Decrypt and unpack record
CryptoResult<byte[], ?> plaintextResult = crypto_.decryptData(cachingMaterialsManager_,
ciphertext);
// Verify the encryption context value
String streamArn = record.getEventSourceARN();
String streamName = streamArn.substring(streamArn.indexOf("/") + 1);
if (!streamName.equals(plaintextResult.getEncryptionContext().get("stream"))) {
throw new IllegalStateException("Wrong Encryption Context!");
}
// Write record to DynamoDB
String jsonItem = new String(plaintextResult.getResult(), StandardCharsets.UTF_8);
System.out.println(jsonItem);
table_.putItem(Item.fromJSON(jsonItem));
}
}
private static class Item {
static Item fromJSON(String jsonText) {
// Parse JSON and create new Item
return new Item();
}
}
}
- Python
-
Ce code Python est déchiffré avec un fournisseur de clé principale en mode découverte. Il permet d' AWS Encryption SDK utiliser n'importe quelle clé d'encapsulation qui a chiffré une clé de données pour la déchiffrer. Le mode strict, dans lequel vous spécifiez les clés d'encapsulation qui peuvent être utilisées pour le déchiffrement, est une bonne pratique.
"""
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 EncryptionSDKClient, DiscoveryAwsKmsMasterKeyProvider, CachingCryptoMaterialsManager, LocalCryptoMaterialsCache, CommitmentPolicy
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 encryption_sdk_client
encryption_sdk_client = EncryptionSDKClient(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
global materials_manager
key_provider = DiscoveryAwsKmsMasterKeyProvider()
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 = encryption_sdk_client.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)