View a markdown version of this page

AWS KMS Portachiavi gerarchici - 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à.

AWS KMS Portachiavi gerarchici

Con il portachiavi AWS KMS gerarchico, puoi proteggere i tuoi materiali crittografici con una chiave KMS di crittografia simmetrica senza chiamare ogni volta che crittografi o decrittografi i dati. AWS KMS È una buona scelta per le applicazioni che devono ridurre al minimo le chiamate e per le applicazioni che possono riutilizzare alcuni materiali crittografici AWS KMS senza violare i requisiti di sicurezza.

Il keyring gerarchico è una soluzione di caching dei materiali crittografici che riduce il numero di AWS KMS chiamate utilizzando chiavi di filiale AWS KMS protette conservate in una tabella Amazon DynamoDB e quindi memorizzando localmente nella cache i materiali delle chiavi di filiale utilizzati nelle operazioni di crittografia e decrittografia. La tabella DynamoDB funge da archivio di chiavi che gestisce e protegge le chiavi di filiale. Memorizza la chiave di ramo attiva e tutte le versioni precedenti della chiave di ramo. La chiave di ramo attiva è la versione più recente della chiave di filiale. Il portachiavi gerarchico utilizza una chiave dati univoca per crittografare ogni messaggio e crittografa ogni chiave di crittografia dei dati per ogni richiesta di crittografia e crittografa ogni chiave di crittografia dei dati con una chiave di wrapping univoca derivata dalla chiave di ramo attiva. Il portachiavi gerarchico dipende dalla gerarchia stabilita tra le chiavi di branch attive e le relative chiavi di wrapping derivate.

Il portachiavi gerarchico utilizza in genere ogni versione della chiave di ramo per soddisfare più richieste. Tuttavia, sei tu a controllare la misura in cui le chiavi di ramo attive vengono riutilizzate e a determinare la frequenza con cui la chiave di ramo attiva viene ruotata. La versione attiva della chiave di diramazione rimane attiva finché non viene ruotata. Le versioni precedenti della chiave di diramazione attiva non verranno utilizzate per eseguire operazioni di crittografia, ma possono comunque essere interrogate e utilizzate nelle operazioni di decrittografia.

Quando si crea un'istanza del portachiavi gerarchico, viene creata una cache locale. Si specifica un limite di cache che definisce il periodo massimo di tempo durante il quale i materiali delle chiavi del ramo vengono archiviati nella cache locale prima che scadano e vengano rimossi dalla cache. Il portachiavi gerarchico effettua una AWS KMS chiamata per decrittografare la chiave di diramazione e assemblare i materiali della chiave di diramazione la prima volta che viene specificato un elemento in un'operazione. branch-key-id Quindi, i materiali delle chiavi di filiale vengono archiviati nella cache locale e riutilizzati per tutte le operazioni di crittografia e decrittografia che lo specificano fino alla scadenza del limite di cache. branch-key-id L'archiviazione dei materiali relativi alle chiavi delle filiali nella cache locale riduce le chiamate. AWS KMS Ad esempio, considera un limite di cache di 15 minuti. Se esegui 10.000 operazioni di crittografia entro tale limite di cache, il AWS KMS portachiavi tradizionale dovrebbe effettuare 10.000 AWS KMS chiamate per soddisfare 10.000 operazioni di crittografia. Se ne hai uno attivobranch-key-id, il portachiavi gerarchico deve effettuare una sola AWS KMS chiamata per soddisfare 10.000 operazioni di crittografia.

La cache locale separa i materiali di crittografia dai materiali di decrittografia. I materiali di crittografia vengono raccolti dalla chiave di filiale attiva e riutilizzati per tutte le operazioni di crittografia fino alla scadenza del limite di cache. I materiali di decrittografia vengono raccolti a partire dall'ID e dalla versione della chiave di filiale identificati nei metadati del campo crittografato e vengono riutilizzati per tutte le operazioni di decrittografia relative all'ID e alla versione della chiave di filiale fino alla scadenza del limite di cache. La cache locale può memorizzare più versioni della stessa chiave di filiale contemporaneamente. Quando la cache locale è configurata per utilizzare abranch key ID supplier, può anche archiviare i materiali delle chiavi di filiale provenienti da più chiavi di filiale attive contemporaneamente.

Nota

Tutte le menzioni del portachiavi gerarchico nel portachiavi gerarchico AWS Encryption SDK si riferiscono al portachiavi gerarchico. AWS KMS

Compatibilità con i linguaggi di programmazione

Il portachiavi Hierarchical è supportato dai seguenti linguaggi e versioni di programmazione:

  • Versione 3. x del SDK di crittografia AWS per Java

  • Versione 4. x e versioni successive di AWS Encryption SDK per .NET

  • Versione 4. x di SDK di crittografia AWS per Python, se utilizzato con la dipendenza MPL opzionale.

  • Versione 1. x di AWS Encryption SDK Rust

  • Versione 0.1. x o versione successiva di AWS Encryption SDK for Go

  • Versione 4.1. x e versioni successive del SDK di crittografia AWS per JavaScript modulo JavaScript Node.js.

    • Il portachiavi AWS KMS gerarchico non è supportato nel for Browser. SDK di crittografia AWS per JavaScript JavaScript Per lo stato attuale e le limitazioni, consulta il repository https://github.com/aws/aws-encryption-sdk-javascript/ aws-encryption-sdk-javascript su. GitHub

Come funziona

Le seguenti procedure dettagliate descrivono come il portachiavi gerarchico assembla i materiali di crittografia e decrittografia e le diverse chiamate effettuate dal portachiavi per le operazioni di crittografia e decrittografia. Per dettagli tecnici sui processi di derivazione della chiave di wrapping e di crittografia delle chiavi di dati in chiaro, vedi Dettagli tecnici sui keyring gerarchici. AWS KMS

Crittografa e firma

La seguente procedura dettagliata descrive come il portachiavi gerarchico assembla i materiali crittografici e ricava una chiave di wrapping univoca.

  1. Il metodo di crittografia richiede al portachiavi gerarchico i materiali crittografici. Il portachiavi genera una chiave dati in testo semplice, quindi verifica se nella cache locale sono presenti materiali di derivazione validi per generare la chiave di wrapping. Se sono disponibili materiali chiave di filiale validi, il portachiavi procede al passaggio 4.

  2. Se non ci sono materiali validi per le chiavi di filiale, il portachiavi gerarchico interroga l'archivio delle chiavi per la chiave di filiale attiva.

    1. L'archivio di chiavi chiama AWS KMS per decrittografare la chiave di filiale attiva e restituisce la chiave di ramo attiva in testo normale. I dati che identificano la chiave di ramo attiva vengono serializzati per fornire dati autenticati (AAD) aggiuntivi nella chiamata di decrittografia a. AWS KMS

    2. Il key store restituisce la chiave di ramo in testo normale e i dati che la identificano, ad esempio la versione della chiave di ramo.

  3. Il portachiavi gerarchico riunisce i materiali delle chiavi di ramo (la chiave di ramo in testo normale e la versione della chiave di ramo) e ne memorizza una copia nella cache locale.

  4. Il portachiavi gerarchico ricava una chiave di raggruppamento univoca dalla chiave di ramo in testo normale e da un sale casuale di 16 byte. Utilizza la chiave di wrapping derivata per crittografare una copia della chiave di dati in testo normale.

Il metodo di crittografia utilizza i materiali di crittografia per crittografare i dati. Per ulteriori informazioni, consulta How the AWS Encryption SDK encrypts data.

Decifra e verifica

La seguente procedura dettagliata descrive come il portachiavi gerarchico assembla i materiali di decrittografia e decrittografa la chiave di dati crittografata.

  1. Il metodo di decrittografia identifica la chiave di dati crittografata dal messaggio crittografato e la passa al portachiavi gerarchico.

  2. Il portachiavi gerarchico deserializza i dati che identificano la chiave di dati crittografata, inclusa la versione della chiave di ramo, il file salt a 16 byte e altre informazioni che descrivono come è stata crittografata la chiave di dati.

    Per ulteriori informazioni, consulta AWS KMS Dettagli tecnici del portachiavi gerarchico.

  3. Il portachiavi gerarchico verifica se nella cache locale sono presenti materiali validi relativi alle chiavi di filiale che corrispondono alla versione della chiave di filiale identificata nel passaggio 2. Se sono disponibili materiali chiave di filiale validi, il portachiavi procede al passaggio 6.

  4. Se non sono disponibili materiali validi per le chiavi di filiale, il portachiavi gerarchico interroga nell'archivio chiavi la chiave di filiale che corrisponde alla versione della chiave di filiale identificata nel passaggio 2.

    1. Il key store chiama AWS KMS per decrittografare la chiave di filiale e restituisce la chiave di ramo attiva in testo normale. I dati che identificano la chiave di ramo attiva vengono serializzati per fornire dati autenticati (AAD) aggiuntivi nella chiamata di decrittografia a. AWS KMS

    2. Il key store restituisce la chiave di ramo in testo normale e i dati che la identificano, ad esempio la versione della chiave di ramo.

  5. Il portachiavi gerarchico riunisce i materiali delle chiavi di ramo (la chiave di ramo in testo normale e la versione della chiave di ramo) e ne memorizza una copia nella cache locale.

  6. Il portachiavi Hierarchical utilizza i materiali delle chiavi di ramo assemblate e il codice salt a 16 byte identificato nel passaggio 2 per riprodurre la chiave di avvolgimento univoca che ha crittografato la chiave di dati.

  7. Il portachiavi gerarchico utilizza la chiave di raggruppamento riprodotta per decrittografare la chiave dati e restituisce la chiave dati in testo normale.

Il metodo di decrittografia utilizza i materiali di decrittografia e la chiave di dati in testo normale per decrittografare il messaggio crittografato. Per ulteriori informazioni, vedi Come decifrare un messaggio crittografato. AWS Encryption SDK

Prerequisiti

Prima di creare e utilizzare un portachiavi gerarchico, assicurati che siano soddisfatti i seguenti prerequisiti.

Autorizzazioni richieste

AWS Encryption SDK Non richiede Account AWS e non dipende da nessuno Servizio AWS. Tuttavia, per utilizzare un portachiavi gerarchico, sono necessarie le seguenti autorizzazioni Account AWS minime sulle AWS KMS key crittografie simmetriche presenti nell'archivio di chiavi.

Autorizzazioni Amazon DynamoDB richieste nella tabella di archiviazione delle chiavi

I principali che interagiscono con il tuo archivio di chiavi necessitano anche delle autorizzazioni sulla tabella DynamoDB. Il set di autorizzazioni dipende dal ruolo.

Utente dell'archivio di chiavi

Un utente dell'archivio di chiavi è il principale che utilizza il portachiavi gerarchico per crittografare e decrittografare i dati. Un utente dell'archivio di chiavi ha bisogno di dynamodb: nella tabella del key store. GetItem

Amministratore del key store

L'amministratore del key store è il responsabile che crea e ruota le chiavi di filiale. Un amministratore dell'archivio chiavi necessita delle seguenti autorizzazioni nella tabella dell'archivio chiavi:

  • Per le letture: dynamodb: GetItem e dynamodb:. ConditionCheckItem

  • Per scritture transazionali: dynamodb: e dynamodb:. ConditionCheckItem PutItem L'archivio gerarchico di chiavi con portachiavi esegue operazioni di scrittura TransactWriteItems; è possibile definire l'ambito delle autorizzazioni di scrittura relative a tale operazione con una condizione. dynamodb:EnclosingOperation

Per ulteriori informazioni sul controllo dell'accesso alle chiavi della filiale e al key store, vedere. Implementazione di autorizzazioni con privilegio minimo

Scegli una cache

Il portachiavi gerarchico riduce il numero di chiamate effettuate AWS KMS memorizzando localmente nella cache i materiali delle chiavi di filiale utilizzati nelle operazioni di crittografia e decrittografia. Prima di creare il portachiavi gerarchico, è necessario decidere il tipo di cache da utilizzare. È possibile utilizzare la cache predefinita o personalizzare la cache per adattarla al meglio alle proprie esigenze.

Il portachiavi gerarchico supporta i seguenti tipi di cache:

Importante

Tutti i tipi di cache supportati sono progettati per supportare ambienti multithread.

Tuttavia, se utilizzato con il SDK di crittografia AWS per Python portachiavi Hierarchical non supporta ambienti multithread. Per ulteriori informazioni, consulta il README.rst file Python nel repository aws-cryptographic-material-providers-library su. https://github.com/aws/aws-cryptographic-material-providers-library/tree/main GitHub

Cache predefinita

Per la maggior parte degli utenti, la cache predefinita soddisfa i requisiti di threading. La cache predefinita è progettata per supportare ambienti fortemente multithread. Quando una voce relativa ai materiali della chiave di filiale scade, la cache predefinita impedisce la chiamata di più thread AWS KMS notificando a un thread che la voce relativa ai materiali della chiave di filiale scadrà con 10 secondi di anticipo. Ciò garantisce che solo un thread invii una richiesta di aggiornamento della cache AWS KMS .

L'impostazione predefinita e StormTracking le cache supportano lo stesso modello di threading, ma è sufficiente specificare la capacità di ingresso per utilizzare la cache predefinita. Per personalizzazioni più granulari della cache, usa il. StormTracking cache

A meno che non si desideri personalizzare il numero di voci relative ai materiali chiave di filiale che possono essere archiviate nella cache locale, non è necessario specificare un tipo di cache quando si crea il portachiavi gerarchico. Se non si specifica un tipo di cache, il portachiavi gerarchico utilizza il tipo di cache predefinito e imposta la capacità di immissione su 1000.

Per personalizzare la cache predefinita, specificate i seguenti valori:

  • Capacità di ingresso: limita il numero di voci relative ai materiali chiave della filiale che possono essere archiviate nella cache locale.

Java
.cache(CacheType.builder() .Default(DefaultCache.builder() .entryCapacity(100) .build())
C# / .NET
CacheType defaultCache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} };
Python
default_cache = CacheTypeDefault( value=DefaultCache( entry_capacity=100 ) )
Rust
let cache: CacheType = CacheType::Default( DefaultCache::builder() .entry_capacity(100) .build()?, );
Go
cache := mpltypes.CacheTypeMemberDefault{ Value: mpltypes.DefaultCache{ EntryCapacity: 100, }, }

MultiThreaded cache

La MultiThreaded cache è sicura da usare in ambienti multithread, ma non fornisce alcuna funzionalità per ridurre al minimo AWS KMS le chiamate Amazon DynamoDB. Di conseguenza, quando una voce relativa ai materiali chiave di una filiale scade, tutti i thread verranno notificati contemporaneamente. Ciò può comportare più AWS KMS chiamate per aggiornare la cache.

Per utilizzare la MultiThreaded cache, specificate i seguenti valori:

  • Capacità di ingresso: limita il numero di voci relative ai materiali chiave della filiale che possono essere archiviate nella cache locale.

  • Dimensione della coda di potatura in entrata: definisce il numero di piante da potare se viene raggiunta la capacità di ingresso.

Java
.cache(CacheType.builder() .MultiThreaded(MultiThreadedCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .build())
C# / .NET
CacheType multithreadedCache = new CacheType { MultiThreaded = new MultiThreadedCache { EntryCapacity = 100, EntryPruningTailSize = 1 } };
Python
multithreaded_cache = CacheTypeMultiThreaded( value=MultiThreadedCache( entry_capacity=100, entry_pruning_tail_size=1 ) )
Rust
CacheType::MultiThreaded( MultiThreadedCache::builder() .entry_capacity(100) .entry_pruning_tail_size(1) .build()?)
Go
var entryPruningTailSize int32 = 1 cache := mpltypes.CacheTypeMemberMultiThreaded{ Value: mpltypes.MultiThreadedCache{ EntryCapacity: 100, EntryPruningTailSize: &entryPruningTailSize, }, }

StormTracking cache

La StormTracking cache è progettata per supportare ambienti fortemente multithread. Quando una voce relativa ai materiali della chiave di filiale scade, la StormTracking cache impedisce la chiamata di più thread AWS KMS notificando a un thread che la voce relativa ai materiali della chiave di filiale scadrà in anticipo. Questo assicura che solo un thread invii una richiesta di aggiornamento della cache AWS KMS . Per ulteriori informazioni, consulta Storm Tracking Cryptographic Materials Cache nel repository GitHub aws-encryption-sdk-specification.

Per utilizzare la cache, specifica i seguenti valori: StormTracking

  • Capacità di ingresso: limita il numero di voci relative ai materiali chiave della filiale che possono essere archiviate nella cache locale.

    Valore predefinito: 1000 voci

  • Dimensione della coda di potatura in entrata: definisce il numero di materiali chiave del ramo da potare contemporaneamente.

    Valore predefinito: 1 voce

  • Periodo di tolleranza: definisce il numero di secondi prima della scadenza in cui viene effettuato un tentativo di aggiornamento dei materiali chiave della filiale.

    Valore predefinito: 10 secondi

  • Intervallo di tolleranza: definisce il numero di secondi tra i tentativi di aggiornamento dei materiali chiave della filiale.

    Valore predefinito: 1 secondo

  • Fan out: definisce il numero di tentativi simultanei che possono essere effettuati per aggiornare i materiali chiave della filiale.

    Valore predefinito: 20 tentativi

  • In flight time to live (TTL): definisce il numero di secondi che mancano al timeout del tentativo di aggiornare i materiali chiave della filiale. Ogni volta che la cache ritorna NoSuchEntry in risposta aGetCacheEntry, quella chiave di diramazione viene considerata attiva finché non viene scritta la stessa chiave insieme a una PutCache voce.

    Valore predefinito: 10 secondi

  • Sospensione: definisce il numero di millisecondi in cui un thread deve rimanere inattivo se viene superato. fanOut

    Valore predefinito: 20 millisecondi

Java
.cache(CacheType.builder() .StormTracking(StormTrackingCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .gracePeriod(10) .graceInterval(1) .fanOut(20) .inFlightTTL(10) .sleepMilli(20) .build())
C# / .NET
CacheType stormTrackingCache = new CacheType { StormTracking = new StormTrackingCache { EntryCapacity = 100, EntryPruningTailSize = 1, FanOut = 20, GraceInterval = 1, GracePeriod = 10, InFlightTTL = 10, SleepMilli = 20 } };
Python
storm_tracking_cache = CacheTypeStormTracking( value=StormTrackingCache( entry_capacity=100, entry_pruning_tail_size=1, fan_out=20, grace_interval=1, grace_period=10, in_flight_ttl=10, sleep_milli=20 ) )
Rust
CacheType::StormTracking( StormTrackingCache::builder() .entry_capacity(100) .entry_pruning_tail_size(1) .grace_period(10) .grace_interval(1) .fan_out(20) .in_flight_ttl(10) .sleep_milli(20) .build()?)
Go
var entryPruningTailSize int32 = 1 cache := mpltypes.CacheTypeMemberStormTracking{ Value: mpltypes.StormTrackingCache{ EntryCapacity: 100, EntryPruningTailSize: &entryPruningTailSize, GraceInterval: 1, GracePeriod: 10, FanOut: 20, InFlightTTL: 10, SleepMilli: 20, }, }

Cache condivisa

Per impostazione predefinita, il portachiavi gerarchico crea una nuova cache locale ogni volta che si crea un'istanza del portachiavi. Tuttavia, la cache condivisa può aiutare a risparmiare memoria consentendo di condividere una cache tra più portachiavi gerarchici. Anziché creare una nuova cache dei materiali crittografici per ogni keyring gerarchico creato, la cache condivisa memorizza solo una cache in memoria, che può essere utilizzata da tutti i portachiavi gerarchici che vi fanno riferimento. La cache condivisa aiuta a ottimizzare l'uso della memoria evitando la duplicazione di materiali crittografici tra i portachiavi. Invece, i portachiavi gerarchici possono accedere alla stessa cache sottostante, riducendo l'ingombro complessivo della memoria.

Quando si crea la cache condivisa, si definisce comunque il tipo di cache. È possibile specificare un Cache predefinitaMultiThreaded cache, o StormTracking cache come tipo di cache o sostituire qualsiasi cache personalizzata compatibile.

Partizioni

Più portachiavi gerarchici possono utilizzare una singola cache condivisa. Quando si crea un portachiavi gerarchico con una cache condivisa, è possibile definire un ID di partizione opzionale. L'ID di partizione distingue il portachiavi gerarchico che sta scrivendo nella cache. Se due portachiavi gerarchici fanno riferimento allo stesso ID di partizione e allo stesso ID di chiave di ramological key store name, i due portachiavi condivideranno le stesse voci della cache nella cache. Se si creano due portachiavi gerarchici con la stessa cache condivisa, ma ID di partizione diversi, ciascun portachiavi accederà alle voci della cache solo dalla propria partizione designata all'interno della cache condivisa. Le partizioni agiscono come divisioni logiche all'interno della cache condivisa, consentendo a ciascun portachiavi gerarchico di operare in modo indipendente sulla propria partizione designata, senza interferire con i dati memorizzati nell'altra partizione.

Se intendi riutilizzare o condividere le voci della cache in una partizione, devi definire il tuo ID di partizione. Quando si passa l'ID della partizione al portachiavi gerarchico, il portachiavi può riutilizzare le voci della cache già presenti nella cache condivisa, anziché dover recuperare e autorizzare nuovamente i materiali delle chiavi di ramo. Se non si specifica un ID di partizione, al portachiavi viene assegnato automaticamente un ID di partizione univoco ogni volta che si crea un'istanza del portachiavi gerarchico.

Le procedure seguenti mostrano come creare una cache condivisa con il tipo di cache predefinito e passarla a un portachiavi gerarchico.

  1. Create una CryptographicMaterialsCache (CMC) utilizzando la Material Providers Library (MPL).

    Java
    // Instantiate the MPL final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); // Create a CacheType object for the Default cache final CacheType cache = CacheType.builder() .Default(DefaultCache.builder().entryCapacity(100).build()) .build(); // Create a CMC using the default cache final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = CreateCryptographicMaterialsCacheInput.builder() .cache(cache) .build(); final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    C# / .NET
    // Instantiate the MPL var materialProviders = new MaterialProviders(new MaterialProvidersConfig()); // Create a CacheType object for the Default cache var cache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} }; // Create a CMC using the default cache var cryptographicMaterialsCacheInput = new CreateCryptographicMaterialsCacheInput {Cache = cache}; var sharedCryptographicMaterialsCache = materialProviders.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    Python
    # Instantiate the MPL mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) # Create a CacheType object for the default cache cache: CacheType = CacheTypeDefault( value=DefaultCache( entry_capacity=100, ) ) # Create a CMC using the default cache cryptographic_materials_cache_input = CreateCryptographicMaterialsCacheInput( cache=cache, ) shared_cryptographic_materials_cache = mat_prov.create_cryptographic_materials_cache( cryptographic_materials_cache_input )
    Rust
    // Instantiate the MPL let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; // Create a CacheType object for the default cache let cache: CacheType = CacheType::Default( DefaultCache::builder() .entry_capacity(100) .build()?, ); // Create a CMC using the default cache let shared_cryptographic_materials_cache: CryptographicMaterialsCacheRef = mpl. create_cryptographic_materials_cache() .cache(cache) .send() .await?;
    Go
    import ( "context" mpl "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygenerated" mpltypes "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygeneratedtypes" ) // Instantiate the MPL matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{}) if err != nil { panic(err) } // Create a CacheType object for the default cache cache := mpltypes.CacheTypeMemberDefault{ Value: mpltypes.DefaultCache{ EntryCapacity: 100, }, } // Create a CMC using the default cache cmcCacheInput := mpltypes.CreateCryptographicMaterialsCacheInput{ Cache: &cache, } sharedCryptographicMaterialsCache, err := matProv.CreateCryptographicMaterialsCache(context.Background(), cmcCacheInput) if err != nil { panic(err) }
  2. Crea un CacheType oggetto per la cache condivisa.

    Passa sharedCryptographicMaterialsCache ciò che hai creato nel passaggio 1 al nuovo CacheType oggetto.

    Java
    // Create a CacheType object for the sharedCryptographicMaterialsCache final CacheType sharedCache = CacheType.builder() .Shared(sharedCryptographicMaterialsCache) .build();
    C# / .NET
    // Create a CacheType object for the sharedCryptographicMaterialsCache var sharedCache = new CacheType { Shared = sharedCryptographicMaterialsCache };
    Python
    # Create a CacheType object for the shared_cryptographic_materials_cache shared_cache: CacheType = CacheTypeShared( value=shared_cryptographic_materials_cache )
    Rust
    // Create a CacheType object for the shared_cryptographic_materials_cache let shared_cache: CacheType = CacheType::Shared(shared_cryptographic_materials_cache);
    Go
    // Create a CacheType object for the shared_cryptographic_materials_cache shared_cache := mpltypes.CacheTypeMemberShared{sharedCryptographicMaterialsCache}
  3. Passa l'sharedCacheoggetto dal passaggio 2 al tuo portachiavi gerarchico.

    Quando crei un portachiavi gerarchico con una cache condivisa, puoi facoltativamente definire una partitionID per condividere le voci della cache tra più portachiavi gerarchici. Se non si specifica un ID di partizione, il portachiavi gerarchico assegna automaticamente al portachiavi un ID di partizione univoco.

    Nota

    I portachiavi gerarchici condivideranno le stesse voci della cache in una cache condivisa se crei due o più portachiavi che fanno riferimento allo stesso ID di partizione e allo stesso ID di chiave di ramo. logical key store name Se non desideri che più portachiavi condividano le stesse voci della cache, devi utilizzare un ID di partizione univoco per ogni portachiavi gerarchico.

    L'esempio seguente crea un portachiavi gerarchico con un branch key ID supplier limite di cache e 600 secondi. Per ulteriori informazioni sui valori definiti nella seguente configurazione gerarchica del portachiavi, vedere. Crea un portachiavi gerarchico

    Java
    // Create the Hierarchical keyring final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(sharedCache) .partitionID(partitionID) .build(); final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    C# / .NET
    // Create the Hierarchical keyring var createKeyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, Cache = sharedCache, TtlSeconds = 600, PartitionId = partitionID }; var keyring = materialProviders.CreateAwsKmsHierarchicalKeyring(createKeyringInput);
    Python
    # Create the Hierarchical keyring keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, branch_key_id_supplier=branch_key_id_supplier, ttl_seconds=600, cache=shared_cache, partition_id=partition_id ) hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( input=keyring_input )
    Rust
    // Create the Hierarchical keyring let keyring1 = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store1) .branch_key_id(branch_key_id.clone()) // CryptographicMaterialsCacheRef is an Rc (Reference Counted), so if you clone it to // pass it to different Hierarchical Keyrings, it will still point to the same // underlying cache, and increment the reference count accordingly. .cache(shared_cache.clone()) .ttl_seconds(600) .partition_id(partition_id.clone()) .send() .await?;
    Go
    // Create the Hierarchical keyring hkeyringInput := mpltypes.CreateAwsKmsHierarchicalKeyringInput{ KeyStore: keyStore1, BranchKeyId: &branchKeyId, TtlSeconds: 600, Cache: &shared_cache, PartitionId: &partitionId, } keyring, err := matProv.CreateAwsKmsHierarchicalKeyring(context.Background(), hkeyringInput) if err != nil { panic(err) }

Crea un portachiavi gerarchico

Per creare un portachiavi gerarchico, è necessario fornire i seguenti valori:

  • Il nome di un archivio di chiavi

    Il nome della tabella DynamoDB creata dall'utente o dall'amministratore del key store per fungere da key store.

  • Un limite di tempo di vita della cache (TTL)

    Il periodo di tempo, in secondi, durante il quale una chiave di filiale inserita nella cache locale può essere utilizzata prima della scadenza. Il limite di cache TTL determina la frequenza con cui il client chiama AWS KMS per autorizzare l'uso delle chiavi di filiale. Questo valore deve essere maggiore di zero. Una volta scaduto il limite di cache TTL, la voce non viene mai pubblicata e verrà rimossa dalla cache locale.

  • Un identificatore della chiave di filiale

    Puoi configurare staticamente branch-key-id quello che identifica una singola chiave di filiale attiva nel tuo key store o fornire un fornitore di ID per le chiavi di filiale.

    Il fornitore dell'ID della chiave di filiale utilizza i campi memorizzati nel contesto di crittografia per determinare quale chiave di filiale è necessaria per decrittografare un record.

    Consigliamo vivamente di utilizzare un fornitore di ID di chiave di filiale per i database multitenant in cui ogni tenant ha la propria chiave di filiale. Puoi utilizzare il fornitore dell'ID della chiave di filiale per creare un nome descrittivo per gli ID delle tue chiavi di filiale in modo da facilitare il riconoscimento dell'ID della chiave di filiale corretto per un tenant specifico. Ad esempio, il nome descrittivo consente di fare riferimento a una chiave di filiale come tenant1 anzichéb3f61619-4d35-48ad-a275-050f87e15122.

    Per le operazioni di decrittografia, è possibile configurare staticamente un singolo portachiavi gerarchico per limitare la decrittografia a un singolo tenant oppure è possibile utilizzare il fornitore dell'ID della chiave di filiale per identificare quale tenant è responsabile della decrittografia di un record.

  • (Facoltativo) Una cache

    Se desideri personalizzare il tipo di cache o il numero di voci relative ai materiali delle chiavi di filiale che possono essere archiviate nella cache locale, specifica il tipo di cache e la capacità di immissione quando inizializzi il portachiavi.

    Il portachiavi gerarchico supporta i seguenti tipi di cache: predefinita,, MultiThreaded e condivisa. StormTracking Per ulteriori informazioni ed esempi che dimostrano come definire ogni tipo di cache, vedere. Scegli una cache

    Se non si specifica una cache, il portachiavi gerarchico utilizza automaticamente il tipo di cache predefinito e imposta la capacità di immissione su 1000.

  • (Facoltativo) Un ID di partizione

    Se si specifica ilCache condivisa, è possibile definire facoltativamente un ID di partizione. L'ID di partizione distingue il portachiavi gerarchico che sta scrivendo nella cache. Se si intende riutilizzare o condividere le voci della cache in una partizione, è necessario definire un ID di partizione personalizzato. È possibile specificare qualsiasi stringa per l'ID della partizione. Se non si specifica un ID di partizione, al portachiavi viene assegnato automaticamente un ID di partizione univoco al momento della creazione.

    Per ulteriori informazioni, consulta Partitions.

    Nota

    I portachiavi gerarchici condivideranno le stesse voci della cache in una cache condivisa se crei due o più portachiavi che fanno riferimento allo stesso ID di partizione e allo stesso ID della chiave di ramo. logical key store name Se non desideri che più portachiavi condividano le stesse voci della cache, devi utilizzare un ID di partizione univoco per ogni portachiavi gerarchico.

  • (Facoltativo) Un elenco di Grant Token

    Se controlli l'accesso alla chiave KMS nel tuo portachiavi gerarchico con le concessioni, devi fornire tutti i token di concessione necessari quando inizializzi il portachiavi.

Gli esempi seguenti mostrano come creare un portachiavi gerarchico con un ID di chiave di ramo staticoCache predefinita, il e un limite di cache TTL di 600 secondi.

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(branchKeyStoreName) .branchKeyId(branch-key-id) .ttlSeconds(600) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyId = branch-key-id, TtlSeconds = 600 }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
Python
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, branch_key_id=branch_key_id, ttl_seconds=600 ) hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( input=keyring_input )
Rust
let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; let hierarchical_keyring = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store.clone()) .branch_key_id(branch_key_id) .ttl_seconds(600) .send() .await?;
Go
matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{}) if err != nil { panic(err) } hkeyringInput := mpltypes.CreateAwsKmsHierarchicalKeyringInput{ KeyStore: keyStore, BranchKeyId: &branchKeyID, TtlSeconds: 600, } hKeyRing, err := matProv.CreateAwsKmsHierarchicalKeyring(context.Background(), hkeyringInput) if err != nil { panic(err) }

Le seguenti procedure mostrano come creare un portachiavi gerarchico con un fornitore di ID chiave di filiale.

  1. Crea un fornitore identificativo chiave di filiale

    L'esempio seguente definisce un fornitore di ID della chiave di filiale che utilizza il contesto di crittografia in fase di crittografia o decrittografia per selezionare l'ID della chiave di filiale per ogni tenant. Per un'implementazione funzionante in ogni lingua, vedi:

    Java
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. public class ExampleBranchKeyIdSupplier implements IBranchKeyIdSupplier { private static String branchKeyIdForTenantA; private static String branchKeyIdForTenantB; public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) { this.branchKeyIdForTenantA = tenant1Id; this.branchKeyIdForTenantB = tenant2Id; } @Override public GetBranchKeyIdOutput GetBranchKeyId(GetBranchKeyIdInput input) { Map<String, String> encryptionContext = input.encryptionContext(); if (!encryptionContext.containsKey("tenant")) { throw new IllegalArgumentException( "EncryptionContext invalid, does not contain expected tenant key value pair."); } String tenantKeyId = encryptionContext.get("tenant"); String branchKeyId; if (tenantKeyId.equals("TenantA")) { branchKeyId = branchKeyIdForTenantA; } else if (tenantKeyId.equals("TenantB")) { branchKeyId = branchKeyIdForTenantB; } else { throw new IllegalArgumentException("Item does not contain valid tenant ID"); } return GetBranchKeyIdOutput.builder().branchKeyId(branchKeyId).build(); } } // Create the branch key ID supplier final IBranchKeyIdSupplier branchKeyIdSupplier = new ExampleBranchKeyIdSupplier( branch-key-ID-tenantA, branch-key-ID-tenantB);
    C# / .NET
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. public class ExampleBranchKeySupplier : BranchKeyIdSupplierBase { private string branchKeyTenantA; private string branchKeyTenantB; public ExampleBranchKeySupplier(string branchKeyTenantA, string branchKeyTenantB) { this.branchKeyTenantA = branchKeyTenantA; this.branchKeyTenantB = branchKeyTenantB; } // The encryption context is used to determine the Branch Key ID. protected override GetBranchKeyIdOutput _GetBranchKeyId(GetBranchKeyIdInput input) { Dictionary<string, string> encryptionContext = input.EncryptionContext; if (!encryptionContext.ContainsKey("tenant")) { throw new Exception("EncryptionContext invalid, does not contain expected tenant key value pair."); } string tenant = encryptionContext["tenant"]; if (tenant.Equals("TenantA")) { return new GetBranchKeyIdOutput { BranchKeyId = branchKeyTenantA }; } if (tenant.Equals("TenantB")) { return new GetBranchKeyIdOutput { BranchKeyId = branchKeyTenantB }; } throw new Exception("Item does not have a valid tenantID."); } } // Create the branch key ID supplier var branchKeyIdSupplier = new ExampleBranchKeySupplier( branch-key-ID-tenantA, branch-key-ID-tenantB);
    Python
    # Define a branch key ID supplier that uses the encryption context to # select a branch key ID for each tenant. class ExampleBranchKeyIdSupplier(IBranchKeyIdSupplier): branch_key_id_for_tenant_A: str branch_key_id_for_tenant_B: str def __init__(self, tenant_1_id, tenant_2_id): self.branch_key_id_for_tenant_A = tenant_1_id self.branch_key_id_for_tenant_B = tenant_2_id def get_branch_key_id( self, param: GetBranchKeyIdInput ) -> GetBranchKeyIdOutput: encryption_context = param.encryption_context if "tenant" not in encryption_context: raise ValueError("EncryptionContext invalid, does not contain expected tenant key value pair.") tenant_key_id = encryption_context.get("tenant") if tenant_key_id == "TenantA": branch_key_id = self.branch_key_id_for_tenant_A elif tenant_key_id == "TenantB": branch_key_id = self.branch_key_id_for_tenant_B else: raise ValueError(f"Item does not contain valid tenant ID: {tenant_key_id=}") return GetBranchKeyIdOutput(branch_key_id=branch_key_id) # Create the branch key ID supplier branch_key_id_supplier: IBranchKeyIdSupplier = ExampleBranchKeyIdSupplier( tenant_1_id=branch_key_id_a, tenant_2_id=branch_key_id_b, )
    Rust
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. pub struct ExampleBranchKeyIdSupplier { branch_key_id_for_tenant_a: String, branch_key_id_for_tenant_b: String, } impl ExampleBranchKeyIdSupplier { pub fn new(tenant_a_id: &str, tenant_b_id: &str) -> Self { Self { branch_key_id_for_tenant_a: tenant_a_id.to_string(), branch_key_id_for_tenant_b: tenant_b_id.to_string(), } } } // The encryption context is used to determine the Branch Key ID. impl BranchKeyIdSupplier for ExampleBranchKeyIdSupplier { fn get_branch_key_id(&self, input: GetBranchKeyIdInput) -> Result<GetBranchKeyIdOutput, Error> { let encryption_context: HashMap<String, String> = input.encryption_context.unwrap(); if !encryption_context.contains_key("tenant") { return Err(Error::AwsCryptographicMaterialProvidersException { message: "EncryptionContext invalid, does not contain expected tenant key value pair.".to_string(), }); } let tenant_key_id: &str = encryption_context["tenant"].as_str(); if tenant_key_id == "TenantA" { Ok(GetBranchKeyIdOutput::builder() .branch_key_id(self.branch_key_id_for_tenant_a.clone()) .build() .unwrap()) } else if tenant_key_id == "TenantB" { Ok(GetBranchKeyIdOutput::builder() .branch_key_id(self.branch_key_id_for_tenant_b.clone()) .build() .unwrap()) } else { Err(Error::AwsCryptographicMaterialProvidersException { message: "Item does not contain valid tenant ID.".to_string(), }) } } } // Create the branch key ID supplier let branch_key_id_supplier = ExampleBranchKeyIdSupplier::new( &branch_key_id_a, &branch_key_id_b, );
    Go
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. type branchKeySupplier struct { branchKeyA string branchKeyB string } // The encryption context is used to determine the Branch Key ID. func (b *branchKeySupplier) GetBranchKeyId(input mpltypes.GetBranchKeyIdInput) (*mpltypes.GetBranchKeyIdOutput, error) { ec := input.EncryptionContext if value, exists := ec["tenant"]; !exists || value == "" { return nil, fmt.Errorf("EncryptionContext invalid, does not contain expected tenant key value pair.") } branchKeyIdentifier := ec["tenant"] if branchKeyIdentifier == "TenantA" { return &mpltypes.GetBranchKeyIdOutput{BranchKeyId: b.branchKeyA}, nil } else if branchKeyIdentifier == "TenantB" { return &mpltypes.GetBranchKeyIdOutput{BranchKeyId: b.branchKeyB}, nil } else { return &mpltypes.GetBranchKeyIdOutput{}, fmt.Errorf("unknown branch key identifier") } } // Create the branch key ID supplier keySupplier := branchKeySupplier{branchKeyA: branchKeyA, branchKeyB: branchKeyB}
  2. Crea un portachiavi gerarchico

    Gli esempi seguenti inizializzano un portachiavi gerarchico con il fornitore dell'ID della chiave di filiale creato nel passaggio 1, un limite di cache TLL di 600 secondi e una dimensione massima della cache di 1000.

    Java
    final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(CacheType.builder() //OPTIONAL .Default(DefaultCache.builder() .entryCapacity(100) .build()) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    C# / .NET
    var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600, Cache = new CacheType { Default = new DefaultCache { EntryCapacity = 100 } } }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    Python
    mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, branch_key_id_supplier=branch_key_id_supplier, ttl_seconds=600, cache=CacheTypeDefault( value=DefaultCache( entry_capacity=100 ) ), ) hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( input=keyring_input )
    Rust
    let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; let hierarchical_keyring = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store.clone()) .branch_key_id_supplier(branch_key_id_supplier) .ttl_seconds(600) .send() .await?;
    Go
    hkeyringInput := mpltypes.CreateAwsKmsHierarchicalKeyringInput{ KeyStore: keyStore, BranchKeyIdSupplier: &keySupplier, TtlSeconds: 600, } hKeyRing, err := matProv.CreateAwsKmsHierarchicalKeyring(context.Background(), hkeyringInput) if err != nil { panic(err) }