Codice di esempio di memorizzazione nella cache delle chiavi dati - AWS Encryption SDK

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Codice di esempio di memorizzazione nella cache delle chiavi dati

Questo esempio di codice crea una semplice implementazione della memorizzazione nella cache delle chiavi di dati con una cache locale in Java e Python. Il codice crea due istanze di una cache locale: una per i produttori di dati che crittografano i dati e l'altra per i consumatori di dati (AWS Lambdafunzioni) che decifrano i dati. Per i dettagli sull'implementazione della memorizzazione nella cache delle chiavi di dati in ogni lingua, consulta la documentazione di Javadoc e Python per. AWS Encryption SDK

La memorizzazione nella cache delle chiavi dati è disponibile per tutti i linguaggi di programmazione supportati da. AWS Encryption SDK

Per esempi completi e testati sull'utilizzo del caching della chiave di dati nel AWS Encryption SDK, consulta:

Producer

Il produttore ottiene una mappa, la converte in JSON, usa la per crittografarla AWS Encryption SDK e invia il record di testo cifrato a un flusso Kinesis in ciascuna di esse. Regione AWS

Il codice definisce un gestore di materiali crittografici per la memorizzazione nella cache (caching CMM) e lo associa a una cache locale e a un provider di chiavi master sottostante. AWS KMS La CMM con memorizzazione nella cache memorizza nella cache le chiavi di dati (e i relativi materiali crittografici) del fornitore della chiave principale. Interagisce inoltre con la cache per conto di SDK e applica le soglie di sicurezza impostate.

Poiché la chiamata al metodo di crittografia specifica una CMM memorizzata nella cache, anziché un normale gestore di materiali crittografici (CMM) o un fornitore di chiavi master, la crittografia utilizzerà la memorizzazione nella cache delle chiavi di dati.

Java

L'esempio seguente utilizza la versione 2. x diSDK di crittografia AWS per Java. Versione 3. x of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. x, puoi anche usare il portachiavi AWS KMS Hierarchical, una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

/* * 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 )

Consumer

Il data consumer è una AWS Lambdafunzione attivata dagli eventi Kinesis. Decripta e deserializza ogni record e scrive il record in testo semplice in una tabella Amazon DynamoDB nella stessa regione.

Come il codice del produttore, il codice consumer consente la memorizzazione nella cache delle chiavi di dati utilizzando un gestore di materiali crittografici (caching CMM) nelle chiamate al metodo di decrittografia.

Il codice Java crea un provider di chiavi master in modalità rigorosa con un valore specificato. AWS KMS key La modalità rigorosa non è richiesta per la decrittografia, ma è una buona pratica. Il codice Python utilizza la modalità di rilevamento, che consente di AWS Encryption SDK utilizzare qualsiasi chiave di wrapping che ha crittografato una chiave di dati per decrittografarla.

Java

L'esempio seguente utilizza la versione 2. x diSDK di crittografia AWS per Java. Versione 3. x of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. x, puoi anche usare il portachiavi AWS KMS Hierarchical, una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

Questo codice crea un provider di chiavi principali per la decrittografia in modalità rigorosa. AWS Encryption SDKPossono utilizzare solo il codice specificato dall'AWS KMS keysutente per decrittografare il messaggio.

/* * 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

Questo codice Python viene decrittografato con un provider di chiavi master in modalità di scoperta. Consente di AWS Encryption SDK utilizzare qualsiasi chiave di wrapping che ha crittografato una chiave di dati per decrittografarla. La modalità rigorosa, in cui si specificano le chiavi di wrapping che possono essere utilizzate per la decrittografia, è una procedura consigliata.

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