Skip to content

Commit d4709e9

Browse files
authored
feat(HierarchyKeyring; CMC): Shared cache across Hierarchy Keyrings (#747)
1 parent 36ede26 commit d4709e9

File tree

17 files changed

+993
-96
lines changed

17 files changed

+993
-96
lines changed

AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders/Model/AwsCryptographyMaterialProvidersTypes.dfy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ module {:extern "software.amazon.cryptography.materialproviders.internaldafny.ty
719719
| SingleThreaded(SingleThreaded: SingleThreadedCache)
720720
| MultiThreaded(MultiThreaded: MultiThreadedCache)
721721
| StormTracking(StormTracking: StormTrackingCache)
722+
| Shared(Shared: ICryptographicMaterialsCache)
722723
class IClientSupplierCallHistory {
723724
ghost constructor() {
724725
GetClient := [];
@@ -823,7 +824,8 @@ module {:extern "software.amazon.cryptography.materialproviders.internaldafny.ty
823824
nameonly branchKeyIdSupplier: Option<IBranchKeyIdSupplier> := Option.None ,
824825
nameonly keyStore: AwsCryptographyKeyStoreTypes.IKeyStoreClient ,
825826
nameonly ttlSeconds: PositiveLong ,
826-
nameonly cache: Option<CacheType> := Option.None
827+
nameonly cache: Option<CacheType> := Option.None ,
828+
nameonly partitionId: Option<string> := Option.None
827829
)
828830
datatype CreateAwsKmsKeyringInput = | CreateAwsKmsKeyringInput (
829831
nameonly kmsKeyId: KmsKeyId ,

AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders/Model/cryptographic-materials-cache.smithy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ union CacheType {
215215
No: NoCache,
216216
SingleThreaded: SingleThreadedCache,
217217
MultiThreaded: MultiThreadedCache,
218-
StormTracking: StormTrackingCache
218+
StormTracking: StormTrackingCache,
219+
@documentation("Shared cache across multiple Hierarchical Keyrings. For this cache type, the user should provide an already constructed CryptographicMaterialsCache to the Hierarchical Keyring at initialization.")
220+
Shared: CryptographicMaterialsCacheReference
219221
}
220222

221223
structure CreateCryptographicMaterialsCacheInput {

AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders/Model/keyrings.smithy

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,11 @@ structure CreateAwsKmsHierarchicalKeyringInput {
339339
@javadoc("How many seconds the Branch Key material is allowed to be reused within the local cache before it is re-retrieved from Amazon DynamoDB and re-authenticated with AWS KMS.")
340340
ttlSeconds: PositiveLong,
341341

342-
@javadoc("Which type of local cache to use.")
342+
@documentation("Sets the type of cache for this Hierarchical Keyring. By providing an already initialized 'Shared' cache, users can determine the scope of the cache. That is, if the cache is shared across other Cryptographic Material Providers, for instance other Hierarchical Keyrings or Caching Cryptographic Materials Managers (Caching CMMs). If any other type of cache in the CacheType union is provided, the Hierarchical Keyring will initialize a cache of that type, to be used with only this Hierarchical Keyring. If not set, a DefaultCache is initialized to be used with only this Hierarchical Keyring with entryCapacity = 1000.")
343343
cache : CacheType
344+
345+
@documentation("Partition ID to distinguish Cryptographic Material Providers (i.e: Keyrings) writing to a cache. If the Partition ID is the same for two Hierarchical Keyrings (or another Material Provider), they can share the same cache entries in the cache.")
346+
partitionId : String
344347
}
345348

346349
// Raw

AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders/src/AwsCryptographyMaterialProvidersOperations.dfy

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
6666
import Kms = Com.Amazonaws.Kms
6767
import Ddb = ComAmazonawsDynamodbTypes
6868
import RequiredEncryptionContextCMM
69+
import UUID
6970

7071
datatype Config = Config(
7172
nameonly crypto: Primitives.AtomicPrimitivesClient
@@ -260,16 +261,76 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
260261
method CreateAwsKmsHierarchicalKeyring (config: InternalConfig, input: CreateAwsKmsHierarchicalKeyringInput)
261262
returns (output: Result<IKeyring, Error>)
262263
{
263-
var maxCacheSize : int32;
264+
// //= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
265+
// //= type=implication
266+
//# If the Hierarchical Keyring does NOT get a `Shared` cache on initialization,
267+
//# it MUST initialize a [cryptographic-materials-cache](../local-cryptographic-materials-cache.md)
268+
//# with the user provided cache limit TTL and the entry capacity.
269+
//# If no `cache` is provided, a `DefaultCache` MUST be configured with entry capacity of 1000.
270+
var cmc;
271+
272+
if input.cache.Some? {
273+
match input.cache.value {
274+
case Shared(c) =>
275+
cmc := c;
276+
case _ =>
277+
cmc :- CreateCryptographicMaterialsCache(
278+
config,
279+
CreateCryptographicMaterialsCacheInput(cache := input.cache.value)
280+
);
281+
}
282+
}
283+
else {
284+
cmc :- CreateCryptographicMaterialsCache(
285+
config,
286+
CreateCryptographicMaterialsCacheInput(
287+
cache := Types.Default(
288+
Types.DefaultCache(entryCapacity := 1000)
289+
)
290+
)
291+
);
292+
}
264293

265-
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
266-
//= type=implication
267-
//# If no max cache size is provided, the crypotgraphic materials cache MUST be configured to a
268-
//# max cache size of 1000.
269-
var cache := if input.cache.Some? then
270-
input.cache.value
271-
else
272-
Types.Default(Types.DefaultCache(entryCapacity := 1000));
294+
// //= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id
295+
// //= type=implication
296+
//# PartitionId can be a string provided by the user. If provided, it MUST be interpreted as UTF8 bytes.
297+
//# If the PartitionId is NOT provided by the user, it MUST be set to the 16 byte representation of a v4 UUID.
298+
var partitionIdBytes : seq<uint8>;
299+
300+
if input.partitionId.Some? {
301+
partitionIdBytes :- UTF8.Encode(input.partitionId.value)
302+
.MapFailure(
303+
e => Types.AwsCryptographicMaterialProvidersException(
304+
message := "Could not UTF-8 Encode Partition ID: " + e
305+
)
306+
);
307+
} else {
308+
var uuid? := UUID.GenerateUUID();
309+
310+
var uuid :- uuid?
311+
.MapFailure(e => Types.AwsCryptographicMaterialProvidersException(message := e));
312+
313+
partitionIdBytes :- UUID.ToByteArray(uuid)
314+
.MapFailure(e => Types.AwsCryptographicMaterialProvidersException(message := e));
315+
}
316+
317+
// //= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#logical-key-store-name
318+
// //= type=implication
319+
//# Logical Key Store Name is set by the user when configuring the Key Store for
320+
//# the Hierarchical Keyring. This is a logical name for the key store.
321+
//# Logical Key Store Name MUST be converted to UTF8 Bytes to be used in
322+
//# the cache identifiers.
323+
var getKeyStoreInfoOutput? := input.keyStore.GetKeyStoreInfo();
324+
var getKeyStoreInfoOutput :- getKeyStoreInfoOutput?
325+
.MapFailure(e => Types.AwsCryptographyKeyStore(AwsCryptographyKeyStore := e));
326+
var logicalKeyStoreName := getKeyStoreInfoOutput.logicalKeyStoreName;
327+
328+
var logicalKeyStoreNameBytes : seq<uint8> :- UTF8.Encode(logicalKeyStoreName)
329+
.MapFailure(
330+
e => Types.AwsCryptographicMaterialProvidersException(
331+
message := "Could not UTF-8 Encode Logical Key Store Name: " + e
332+
)
333+
);
273334

274335
:- Need(input.branchKeyId.None? || input.branchKeyIdSupplier.None?,
275336
Types.AwsCryptographicMaterialProvidersException(
@@ -279,14 +340,14 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
279340
Types.AwsCryptographicMaterialProvidersException(
280341
message := "Must initialize keyring with either branchKeyId or BranchKeyIdSupplier."));
281342

282-
var cmc :- CreateCryptographicMaterialsCache(config, CreateCryptographicMaterialsCacheInput(cache := cache));
283343
var keyring := new AwsKmsHierarchicalKeyring.AwsKmsHierarchicalKeyring(
284344
keyStore := input.keyStore,
285345
branchKeyId := input.branchKeyId,
286346
branchKeyIdSupplier := input.branchKeyIdSupplier,
287347
ttlSeconds := input.ttlSeconds,
288-
// maxCacheSize := maxCacheSize,
289348
cmc := cmc,
349+
partitionIdBytes := partitionIdBytes,
350+
logicalKeyStoreNameBytes := logicalKeyStoreNameBytes,
290351
cryptoPrimitives := config.crypto
291352
);
292353
return Success(keyring);
@@ -735,6 +796,10 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
735796
);
736797
var synCmc := new StormTrackingCMC.StormTrackingCMC(cmc);
737798
return Success(synCmc);
799+
case Shared(c) =>
800+
var exception := Types.AwsCryptographicMaterialProvidersException(
801+
message := "CreateCryptographicMaterialsCache should never be called with Shared CacheType.");
802+
return Failure(exception);
738803
}
739804
}
740805

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
include "../../Model/AwsCryptographyMaterialProvidersTypes.dfy"
5+
6+
module CacheConstants {
7+
import opened StandardLibrary.UInt
8+
import Seq
9+
10+
// Constants defined for cache identifier formulae
11+
12+
// Null Byte
13+
const NULL_BYTE : seq<uint8> := [0x00]
14+
15+
// Resource Id
16+
const RESOURCE_ID_CACHING_CMM: seq<uint8> := [0x01]
17+
const RESOURCE_ID_HIERARCHICAL_KEYRING: seq<uint8> := [0x02]
18+
19+
// Scope Id
20+
const SCOPE_ID_ENCRYPT: seq<uint8> := [0x01]
21+
const SCOPE_ID_DECRYPT: seq<uint8> := [0x02]
22+
const SCOPE_ID_SEARCHABLE_ENCRYPTION: seq<uint8> := [0x03]
23+
}

0 commit comments

Comments
 (0)