Skip to content

Commit b7a6159

Browse files
committed
add partition ID and cache
1 parent 57f6ea6 commit b7a6159

File tree

14 files changed

+358
-37
lines changed

14 files changed

+358
-37
lines changed

DynamoDbEncryption/dafny/DynamoDbEncryption/Model/AwsCryptographyDbEncryptionSdkDynamoDbTypes.dfy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ module {:extern "software.amazon.cryptography.dbencryptionsdk.dynamodb.internald
389389
}
390390
datatype SingleKeyStore = | SingleKeyStore (
391391
nameonly keyId: string ,
392-
nameonly cacheTTL: Option<int32> := Option.None ,
392+
nameonly cacheTTL: int32 ,
393393
nameonly cache: Option<AwsCryptographyMaterialProvidersTypes.CacheType> := Option.None ,
394394
nameonly partitionId: Option<string> := Option.None
395395
)

DynamoDbEncryption/dafny/DynamoDbEncryption/Model/DynamoDbEncryption.smithy

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,11 +713,12 @@ structure SingleKeyStore {
713713
@required
714714
@javadoc("The Beacon Key ID.")
715715
keyId : String,
716-
@javadoc("How long (in seconds) the beacon key material is cached locally before it is re-retrieved from DynamoDB and re-authed with AWS KMS. Provide only one of cacheTTL or cache.")
716+
@required
717+
@javadoc("How long (in seconds) the beacon key material is cached locally before it is re-retrieved from DynamoDB and re-authed with AWS KMS.")
717718
cacheTTL: Integer,
718-
@documentation("Provide the Shared Cache for Searchable Encryption. Provide only one of cacheTTL or cache.")
719+
@documentation("Provide the Shared Cache for Searchable Encryption.")
719720
cache : CacheType,
720-
@documentation("Partition ID to share DynamoDB Interceptors. TODO: Update description")
721+
@documentation("Partition ID to distinguish Beacon Key Sources writing to a cache. If the Partition ID is the same for two Beacon Key Sources, they can share the same cache entries in the cache.")
721722
partitionId: String
722723
}
723724

@@ -738,7 +739,7 @@ structure MultiKeyStore {
738739
cacheTTL: Integer,
739740
@javadoc("Which type of local cache to use.")
740741
cache : CacheType,
741-
@documentation("Partition ID to share DynamoDB Interceptors. TODO: Update description")
742+
@documentation("Partition ID to distinguish Beacon Key Sources writing to a cache. If the Partition ID is the same for two Beacon Key Sources, they can share the same cache entries in the cache.")
742743
partitionId: String
743744
}
744745

DynamoDbEncryption/dafny/DynamoDbEncryption/src/ConfigToInfo.dfy

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,11 @@ module SearchConfigToInfo {
136136
else
137137
MPT.Default(Default := MPT.DefaultCache(entryCapacity := 1000))
138138
else
139-
MPT.Default(Default := MPT.DefaultCache(entryCapacity := 1));
139+
if config.single.cache.Some? then
140+
config.single.cache.value
141+
else
142+
MPT.Default(Default := MPT.DefaultCache(entryCapacity := 1));
140143

141-
// TODO : Add check that customers only provide either cacheTTL or cache in case of SingleKeyStore
142144
var cache;
143145
if cacheType.Shared? {
144146
cache := cacheType.Shared;
@@ -155,15 +157,21 @@ module SearchConfigToInfo {
155157

156158
var partitionIdBytes : seq<uint8>;
157159

158-
if outer.keyring.Some? {
159-
if outer.keyring.value.partitionId.Some? {
160-
partitionIdBytes :- UTF8.Encode(outer.keyring.value.partitionId.value)
161-
.MapFailure(
162-
e => Error.DynamoDbEncryptionException(
163-
message := "Could not UTF-8 Encode Partition ID: " + e
164-
)
165-
);
166-
}
160+
if config.multi? && config.multi.partitionId.Some? {
161+
partitionIdBytes :- UTF8.Encode(config.multi.partitionId.value)
162+
.MapFailure(
163+
e => Error.DynamoDbEncryptionException(
164+
message := "Could not UTF-8 Encode Partition ID from MultiKeyStore: " + e
165+
)
166+
);
167+
}
168+
if config.single? && config.single.partitionId.Some? {
169+
partitionIdBytes :- UTF8.Encode(config.single.partitionId.value)
170+
.MapFailure(
171+
e => Error.DynamoDbEncryptionException(
172+
message := "Could not UTF-8 Encode Partition ID from SingleKeyStore: " + e
173+
)
174+
);
167175
}
168176
else {
169177
var uuid? := UUID.GenerateUUID();

DynamoDbEncryption/dafny/DynamoDbEncryption/src/SearchInfo.dfy

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ module SearchableEncryptionInfo {
155155
{
156156
if keyLoc.SingleLoc? {
157157
:- Need(keyId.DontUseKeyId?, E("KeyID should not be supplied with a SingleKeyStore"));
158-
var theMap :- getKeysCache(stdNames, keyLoc.keyId, partitionIdBytes);
158+
var theMap :- getKeysCache(stdNames, keyLoc.keyId, cacheTTL as MP.PositiveLong, partitionIdBytes);
159159
return Success(Keys(theMap));
160160
} else if keyLoc.LiteralLoc? {
161161
:- Need(keyId.DontUseKeyId?, E("KeyID should not be supplied with a LiteralKeyStore"));
@@ -165,7 +165,7 @@ module SearchableEncryptionInfo {
165165
match keyId {
166166
case DontUseKeyId => return Failure(E("KeyID must not be supplied with a MultiKeyStore"));
167167
case ShouldHaveKeyId => return Success(ShouldHaveKeys);
168-
case KeyId(id) => var theMap :- getKeysCache(stdNames, id, partitionIdBytes); return Success(Keys(theMap));
168+
case KeyId(id) => var theMap :- getKeysCache(stdNames, id, cacheTTL as MP.PositiveLong, partitionIdBytes); return Success(Keys(theMap));
169169
}
170170
}
171171
}
@@ -182,9 +182,22 @@ module SearchableEncryptionInfo {
182182
return Success(keyLoc.keys);
183183
}
184184

185+
// Checks if (time_now - cache creation time of the extracted cache entry) is less than the allowed
186+
// TTL of the current Beacon Key Source calling the getEntry method from the cache.
187+
// Mitigates risk if another Beacon Key Source wrote the entry with a longer TTL.
188+
predicate method cacheEntryWithinLimits(
189+
creationTime: MP.PositiveLong,
190+
now: MP.PositiveLong,
191+
ttlSeconds: MP.PositiveLong
192+
): (output: bool)
193+
{
194+
now - creationTime <= ttlSeconds as MP.PositiveLong
195+
}
196+
185197
method getKeysCache(
186198
stdNames : seq<string>,
187199
keyId : string,
200+
cacheTTL : MP.PositiveLong,
188201
partitionIdBytes : seq<uint8>
189202
)
190203
returns (output : Result<HmacKeyMap, Error>)
@@ -269,8 +282,21 @@ module SearchableEncryptionInfo {
269282
return Failure(AwsCryptographyMaterialProviders(AwsCryptographyMaterialProviders:=getCacheOutput.error));
270283
}
271284

272-
// TODO: Add cacheEntryWithinLimits
273-
if getCacheOutput.Failure? {
285+
var now := Time.GetCurrent();
286+
287+
// //= specification/searchable-encryption/search-config.md#<heading>
288+
//# If using a `Shared` cache across multiple Beacon Key Sources,
289+
//# different Key Sources having the same `beaconKey` can have different TTLs.
290+
//# In such a case, the expiry time in the cache is set according to the Beacon Key Source that populated the cache.
291+
//# There MUST be a check (cacheEntryWithinLimits) to make sure that for the cache entry found, who's TTL has NOT expired,
292+
//# `time.now() - cacheEntryCreationTime <= ttlSeconds` is true and
293+
//# valid for TTL of the Beacon Key Source getting the cache entry.
294+
//# If this is NOT true, then we MUST treat the cache entry as expired.
295+
if getCacheOutput.Failure? || !cacheEntryWithinLimits(
296+
creationTime := getCacheOutput.value.creationTime,
297+
now := now,
298+
ttlSeconds := cacheTTL
299+
) {
274300
//= specification/searchable-encryption/search-config.md#beacon-keys
275301
//# Beacon keys MUST be obtained from the configured [Beacon Key Source](#beacon-key-source).
276302
var maybeRawBeaconKeyMaterials := store.GetBeaconKey(

DynamoDbEncryption/runtimes/java/src/main/smithy-generated/software/amazon/cryptography/dbencryptionsdk/dynamodb/ToDafny.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,19 @@ public static MultiKeyStore MultiKeyStore(
668668
)
669669
)
670670
: Option.create_None(CacheType._typeDescriptor());
671-
return new MultiKeyStore(keyFieldName, cacheTTL, cache);
671+
Option<DafnySequence<? extends Character>> partitionId;
672+
partitionId =
673+
Objects.nonNull(nativeValue.partitionId())
674+
? Option.create_Some(
675+
DafnySequence._typeDescriptor(TypeDescriptor.CHAR),
676+
software.amazon.smithy.dafny.conversion.ToDafny.Simple.CharacterSequence(
677+
nativeValue.partitionId()
678+
)
679+
)
680+
: Option.create_None(
681+
DafnySequence._typeDescriptor(TypeDescriptor.CHAR)
682+
);
683+
return new MultiKeyStore(keyFieldName, cacheTTL, cache, partitionId);
672684
}
673685

674686
public static PartOnly PartOnly(
@@ -747,7 +759,29 @@ public static SingleKeyStore SingleKeyStore(
747759
);
748760
Integer cacheTTL;
749761
cacheTTL = (nativeValue.cacheTTL());
750-
return new SingleKeyStore(keyId, cacheTTL);
762+
Option<CacheType> cache;
763+
cache =
764+
Objects.nonNull(nativeValue.cache())
765+
? Option.create_Some(
766+
CacheType._typeDescriptor(),
767+
software.amazon.cryptography.materialproviders.ToDafny.CacheType(
768+
nativeValue.cache()
769+
)
770+
)
771+
: Option.create_None(CacheType._typeDescriptor());
772+
Option<DafnySequence<? extends Character>> partitionId;
773+
partitionId =
774+
Objects.nonNull(nativeValue.partitionId())
775+
? Option.create_Some(
776+
DafnySequence._typeDescriptor(TypeDescriptor.CHAR),
777+
software.amazon.smithy.dafny.conversion.ToDafny.Simple.CharacterSequence(
778+
nativeValue.partitionId()
779+
)
780+
)
781+
: Option.create_None(
782+
DafnySequence._typeDescriptor(TypeDescriptor.CHAR)
783+
);
784+
return new SingleKeyStore(keyId, cacheTTL, cache, partitionId);
751785
}
752786

753787
public static StandardBeacon StandardBeacon(

DynamoDbEncryption/runtimes/java/src/main/smithy-generated/software/amazon/cryptography/dbencryptionsdk/dynamodb/ToNative.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,13 @@ public static MultiKeyStore MultiKeyStore(
574574
)
575575
);
576576
}
577+
if (dafnyValue.dtor_partitionId().is_Some()) {
578+
nativeBuilder.partitionId(
579+
software.amazon.smithy.dafny.conversion.ToNative.Simple.String(
580+
dafnyValue.dtor_partitionId().dtor_value()
581+
)
582+
);
583+
}
577584
return nativeBuilder.build();
578585
}
579586

@@ -653,6 +660,20 @@ public static SingleKeyStore SingleKeyStore(
653660
)
654661
);
655662
nativeBuilder.cacheTTL((dafnyValue.dtor_cacheTTL()));
663+
if (dafnyValue.dtor_cache().is_Some()) {
664+
nativeBuilder.cache(
665+
software.amazon.cryptography.materialproviders.ToNative.CacheType(
666+
dafnyValue.dtor_cache().dtor_value()
667+
)
668+
);
669+
}
670+
if (dafnyValue.dtor_partitionId().is_Some()) {
671+
nativeBuilder.partitionId(
672+
software.amazon.smithy.dafny.conversion.ToNative.Simple.String(
673+
dafnyValue.dtor_partitionId().dtor_value()
674+
)
675+
);
676+
}
656677
return nativeBuilder.build();
657678
}
658679

DynamoDbEncryption/runtimes/java/src/main/smithy-generated/software/amazon/cryptography/dbencryptionsdk/dynamodb/model/MultiKeyStore.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,16 @@ public class MultiKeyStore {
2626
*/
2727
private final CacheType cache;
2828

29+
/**
30+
* Partition ID to distinguish Beacon Key Sources writing to a cache. If the Partition ID is the same for two Beacon Key Sources, they can share the same cache entries in the cache.
31+
*/
32+
private final String partitionId;
33+
2934
protected MultiKeyStore(BuilderImpl builder) {
3035
this.keyFieldName = builder.keyFieldName();
3136
this.cacheTTL = builder.cacheTTL();
3237
this.cache = builder.cache();
38+
this.partitionId = builder.partitionId();
3339
}
3440

3541
/**
@@ -53,6 +59,13 @@ public CacheType cache() {
5359
return this.cache;
5460
}
5561

62+
/**
63+
* @return Partition ID to distinguish Beacon Key Sources writing to a cache. If the Partition ID is the same for two Beacon Key Sources, they can share the same cache entries in the cache.
64+
*/
65+
public String partitionId() {
66+
return this.partitionId;
67+
}
68+
5669
public Builder toBuilder() {
5770
return new BuilderImpl(this);
5871
}
@@ -92,6 +105,16 @@ public interface Builder {
92105
*/
93106
CacheType cache();
94107

108+
/**
109+
* @param partitionId Partition ID to distinguish Beacon Key Sources writing to a cache. If the Partition ID is the same for two Beacon Key Sources, they can share the same cache entries in the cache.
110+
*/
111+
Builder partitionId(String partitionId);
112+
113+
/**
114+
* @return Partition ID to distinguish Beacon Key Sources writing to a cache. If the Partition ID is the same for two Beacon Key Sources, they can share the same cache entries in the cache.
115+
*/
116+
String partitionId();
117+
95118
MultiKeyStore build();
96119
}
97120

@@ -103,12 +126,15 @@ static class BuilderImpl implements Builder {
103126

104127
protected CacheType cache;
105128

129+
protected String partitionId;
130+
106131
protected BuilderImpl() {}
107132

108133
protected BuilderImpl(MultiKeyStore model) {
109134
this.keyFieldName = model.keyFieldName();
110135
this.cacheTTL = model.cacheTTL();
111136
this.cache = model.cache();
137+
this.partitionId = model.partitionId();
112138
}
113139

114140
public Builder keyFieldName(String keyFieldName) {
@@ -138,6 +164,15 @@ public CacheType cache() {
138164
return this.cache;
139165
}
140166

167+
public Builder partitionId(String partitionId) {
168+
this.partitionId = partitionId;
169+
return this;
170+
}
171+
172+
public String partitionId() {
173+
return this.partitionId;
174+
}
175+
141176
public MultiKeyStore build() {
142177
if (Objects.isNull(this.keyFieldName())) {
143178
throw new IllegalArgumentException(

0 commit comments

Comments
 (0)