Skip to content

Commit aadb18e

Browse files
auto commit
1 parent 007a343 commit aadb18e

File tree

7 files changed

+360
-405
lines changed

7 files changed

+360
-405
lines changed

Examples/runtimes/net/src/migration/PlaintextToAWSDBE/awsdbe/MigrationStep1Test.cs

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,41 +38,36 @@ public async Task TestMigrationStep1()
3838
string partitionKey = Guid.NewGuid().ToString();
3939
string[] sortKeys = { "0", "1", "2", "3" };
4040

41-
try
42-
{
43-
// Given: Step 0 has succeeded
44-
bool success = await MigrationStep0.MigrationStep0Example(tableName, partitionKey, sortKeys[0], sortKeys[0]);
45-
Assert.True(success, "MigrationStep0 should complete successfully");
41+
// Given: Step 0 has succeeded
42+
bool success = await MigrationStep0.MigrationStep0Example(tableName, partitionKey, sortKeys[0], sortKeys[0]);
43+
Assert.True(success, "MigrationStep0 should complete successfully");
4644

47-
// Successfully executes step 1
48-
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[1]);
49-
Assert.True(success, "MigrationStep1 should complete successfully");
45+
// Successfully executes step 1
46+
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[1]);
47+
Assert.True(success, "MigrationStep1 should complete successfully");
5048

51-
// When: Execute Step 1 with sortReadValue=0, Then: Success (i.e. can read plaintext values from Step 0)
52-
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[0]);
53-
Assert.True(success, "MigrationStep1 should be able to read items written by Step 0");
49+
// When: Execute Step 1 with sortReadValue=0, Then: Success (i.e. can read plaintext values from Step 0)
50+
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[0]);
51+
Assert.True(success, "MigrationStep1 should be able to read items written by Step 0");
5452

55-
// Given: Step 2 has succeeded
56-
success = await MigrationStep2.MigrationStep2Example(kmsKeyID, tableName, partitionKey, sortKeys[2], sortKeys[2]);
57-
Assert.True(success, "MigrationStep2 should complete successfully");
53+
// Given: Step 2 has succeeded
54+
success = await MigrationStep2.MigrationStep2Example(kmsKeyID, tableName, partitionKey, sortKeys[2], sortKeys[2]);
55+
Assert.True(success, "MigrationStep2 should complete successfully");
5856

59-
// When: Execute Step 1 with sortReadValue=2, Then: Success (i.e. can read encrypted values from Step 2)
60-
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[2]);
61-
Assert.True(success, "MigrationStep1 should be able to read items written by Step 2");
57+
// When: Execute Step 1 with sortReadValue=2, Then: Success (i.e. can read encrypted values from Step 2)
58+
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[2]);
59+
Assert.True(success, "MigrationStep1 should be able to read items written by Step 2");
6260

63-
// Given: Step 3 has succeeded
64-
success = await MigrationStep3.MigrationStep3Example(kmsKeyID, tableName, partitionKey, sortKeys[3], sortKeys[3]);
65-
Assert.True(success, "MigrationStep3 should complete successfully");
61+
// Given: Step 3 has succeeded
62+
success = await MigrationStep3.MigrationStep3Example(kmsKeyID, tableName, partitionKey, sortKeys[3], sortKeys[3]);
63+
Assert.True(success, "MigrationStep3 should complete successfully");
6664

67-
// When: Execute Step 1 with sortReadValue=3, Then: Success (i.e. can read encrypted values from Step 3)
68-
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[3]);
69-
Assert.True(success, "MigrationStep1 should be able to read items written by Step 3");
70-
}
71-
finally
72-
{
73-
// Cleanup
74-
await MigrationUtils.CleanupItems(tableName, partitionKey, sortKeys);
75-
}
65+
// When: Execute Step 1 with sortReadValue=3, Then: Success (i.e. can read encrypted values from Step 3)
66+
success = await MigrationStep1.MigrationStep1Example(kmsKeyID, tableName, partitionKey, sortKeys[1], sortKeys[3]);
67+
Assert.True(success, "MigrationStep1 should be able to read items written by Step 3");
68+
69+
// Cleanup
70+
await MigrationUtils.CleanupItems(tableName, partitionKey, sortKeys);
7671
}
7772
}
7873
}

Examples/runtimes/net/src/migration/PlaintextToAWSDBE/awsdbe/MigrationStep2.cs

Lines changed: 100 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -39,129 +39,121 @@ public class MigrationStep2
3939
{
4040
public static async Task<bool> MigrationStep2Example(string kmsKeyId, string ddbTableName, string partitionKeyValue, string sortKeyWriteValue, string sortKeyReadValue)
4141
{
42-
try
43-
{
44-
// 1. Create a Keyring. This Keyring will be responsible for protecting the data keys that protect your data.
45-
// For this example, we will create a AWS KMS Keyring with the AWS KMS Key we want to use.
46-
// We will use the `CreateMrkMultiKeyring` method to create this keyring,
47-
// as it will correctly handle both single region and Multi-Region KMS Keys.
48-
var matProv = new MaterialProviders(new MaterialProvidersConfig());
49-
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
50-
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
51-
52-
// 2. Configure which attributes are encrypted and/or signed when writing new items.
53-
// For each attribute that may exist on the items we plan to write to our DynamoDbTable,
54-
// we must explicitly configure how they should be treated during item encryption:
55-
// - ENCRYPT_AND_SIGN: The attribute is encrypted and included in the signature
56-
// - SIGN_ONLY: The attribute not encrypted, but is still included in the signature
57-
// - DO_NOTHING: The attribute is not encrypted and not included in the signature
58-
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
59-
{
60-
["partition_key"] = CryptoAction.SIGN_ONLY, // Our partition attribute must be SIGN_ONLY
61-
["sort_key"] = CryptoAction.SIGN_ONLY, // Our sort attribute must be SIGN_ONLY
62-
["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
63-
["attribute2"] = CryptoAction.SIGN_ONLY,
64-
["attribute3"] = CryptoAction.DO_NOTHING
65-
};
42+
// 1. Create a Keyring. This Keyring will be responsible for protecting the data keys that protect your data.
43+
// For this example, we will create a AWS KMS Keyring with the AWS KMS Key we want to use.
44+
// We will use the `CreateMrkMultiKeyring` method to create this keyring,
45+
// as it will correctly handle both single region and Multi-Region KMS Keys.
46+
var matProv = new MaterialProviders(new MaterialProvidersConfig());
47+
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
48+
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
6649

67-
// 3. Configure which attributes we expect to be excluded in the signature
68-
// when reading items.
69-
// For this example, we will explicitly list the attributes that are not signed.
70-
var unsignedAttributes = new List<string> { "attribute3" };
50+
// 2. Configure which attributes are encrypted and/or signed when writing new items.
51+
// For each attribute that may exist on the items we plan to write to our DynamoDbTable,
52+
// we must explicitly configure how they should be treated during item encryption:
53+
// - ENCRYPT_AND_SIGN: The attribute is encrypted and included in the signature
54+
// - SIGN_ONLY: The attribute not encrypted, but is still included in the signature
55+
// - DO_NOTHING: The attribute is not encrypted and not included in the signature
56+
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
57+
{
58+
["partition_key"] = CryptoAction.SIGN_ONLY, // Our partition attribute must be SIGN_ONLY
59+
["sort_key"] = CryptoAction.SIGN_ONLY, // Our sort attribute must be SIGN_ONLY
60+
["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
61+
["attribute2"] = CryptoAction.SIGN_ONLY,
62+
["attribute3"] = CryptoAction.DO_NOTHING
63+
};
7164

72-
// 4. Create the DynamoDb Encryption configuration for the table we will be writing to.
73-
// This configuration uses PlaintextOverride.FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ
74-
// which means:
75-
// - Write: Items are forbidden to be written as plaintext.
76-
// Items will be written as encrypted items.
77-
// - Read: Items are allowed to be read as plaintext.
78-
// Items are allowed to be read as encrypted items.
79-
var tableConfig = new DynamoDbTableEncryptionConfig
80-
{
81-
LogicalTableName = ddbTableName,
82-
PartitionKeyName = "partition_key",
83-
SortKeyName = "sort_key",
84-
AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
85-
Keyring = kmsKeyring,
86-
AllowedUnsignedAttributes = unsignedAttributes,
87-
PlaintextOverride = PlaintextOverride.FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ
88-
};
65+
// 3. Configure which attributes we expect to be excluded in the signature
66+
// when reading items.
67+
// For this example, we will explicitly list the attributes that are not signed.
68+
var unsignedAttributes = new List<string> { "attribute3" };
8969

90-
var tableConfigs = new Dictionary<string, DynamoDbTableEncryptionConfig>
91-
{
92-
[ddbTableName] = tableConfig
93-
};
70+
// 4. Create the DynamoDb Encryption configuration for the table we will be writing to.
71+
// This configuration uses PlaintextOverride.FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ
72+
// which means:
73+
// - Write: Items are forbidden to be written as plaintext.
74+
// Items will be written as encrypted items.
75+
// - Read: Items are allowed to be read as plaintext.
76+
// Items are allowed to be read as encrypted items.
77+
var tableConfig = new DynamoDbTableEncryptionConfig
78+
{
79+
LogicalTableName = ddbTableName,
80+
PartitionKeyName = "partition_key",
81+
SortKeyName = "sort_key",
82+
AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
83+
Keyring = kmsKeyring,
84+
AllowedUnsignedAttributes = unsignedAttributes,
85+
PlaintextOverride = PlaintextOverride.FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ
86+
};
9487

95-
// 5. Create a new AWS SDK DynamoDb client using the TableEncryptionConfigs
96-
var ddb = new Client.DynamoDbClient(
97-
new DynamoDbTablesEncryptionConfig { TableEncryptionConfigs = tableConfigs });
88+
var tableConfigs = new Dictionary<string, DynamoDbTableEncryptionConfig>
89+
{
90+
[ddbTableName] = tableConfig
91+
};
9892

99-
// 6. Put an item into our table using the above client.
100-
// This item will be encrypted due to our PlaintextOverride configuration.
101-
string encryptedAndSignedValue = MigrationUtils.ENCRYPTED_AND_SIGNED_VALUE;
102-
string signOnlyValue = MigrationUtils.SIGN_ONLY_VALUE;
103-
string doNothingValue = MigrationUtils.DO_NOTHING_VALUE;
104-
var item = new Dictionary<string, AttributeValue>
105-
{
106-
["partition_key"] = new AttributeValue { S = partitionKeyValue },
107-
["sort_key"] = new AttributeValue { N = sortKeyWriteValue },
108-
["attribute1"] = new AttributeValue { S = encryptedAndSignedValue },
109-
["attribute2"] = new AttributeValue { S = signOnlyValue },
110-
["attribute3"] = new AttributeValue { S = doNothingValue }
111-
};
93+
// 5. Create a new AWS SDK DynamoDb client using the TableEncryptionConfigs
94+
var ddb = new Client.DynamoDbClient(
95+
new DynamoDbTablesEncryptionConfig { TableEncryptionConfigs = tableConfigs });
11296

113-
var putRequest = new PutItemRequest
114-
{
115-
TableName = ddbTableName,
116-
Item = item
117-
};
97+
// 6. Put an item into our table using the above client.
98+
// This item will be encrypted due to our PlaintextOverride configuration.
99+
string encryptedAndSignedValue = MigrationUtils.ENCRYPTED_AND_SIGNED_VALUE;
100+
string signOnlyValue = MigrationUtils.SIGN_ONLY_VALUE;
101+
string doNothingValue = MigrationUtils.DO_NOTHING_VALUE;
102+
var item = new Dictionary<string, AttributeValue>
103+
{
104+
["partition_key"] = new AttributeValue { S = partitionKeyValue },
105+
["sort_key"] = new AttributeValue { N = sortKeyWriteValue },
106+
["attribute1"] = new AttributeValue { S = encryptedAndSignedValue },
107+
["attribute2"] = new AttributeValue { S = signOnlyValue },
108+
["attribute3"] = new AttributeValue { S = doNothingValue }
109+
};
118110

119-
var putResponse = await ddb.PutItemAsync(putRequest);
120-
Debug.Assert(putResponse.HttpStatusCode == HttpStatusCode.OK);
111+
var putRequest = new PutItemRequest
112+
{
113+
TableName = ddbTableName,
114+
Item = item
115+
};
121116

122-
// 7. Get an item back from the table using the same client.
123-
// If this is an item written in plaintext (i.e. any item written
124-
// during Step 0 or 1), then the item will still be in plaintext.
125-
// If this is an item that was encrypted client-side (i.e. any item written
126-
// during Step 2 or after), then the item will be decrypted client-side
127-
// and surfaced as a plaintext item.
128-
var key = new Dictionary<string, AttributeValue>
129-
{
130-
["partition_key"] = new AttributeValue { S = partitionKeyValue },
131-
["sort_key"] = new AttributeValue { N = sortKeyReadValue }
132-
};
117+
var putResponse = await ddb.PutItemAsync(putRequest);
118+
Debug.Assert(putResponse.HttpStatusCode == HttpStatusCode.OK);
133119

134-
var getRequest = new GetItemRequest
135-
{
136-
TableName = ddbTableName,
137-
Key = key,
138-
// In this example we configure a strongly consistent read
139-
// because we perform a read immediately after a write (for demonstrative purposes).
140-
// By default, reads are only eventually consistent.
141-
ConsistentRead = true
142-
};
120+
// 7. Get an item back from the table using the same client.
121+
// If this is an item written in plaintext (i.e. any item written
122+
// during Step 0 or 1), then the item will still be in plaintext.
123+
// If this is an item that was encrypted client-side (i.e. any item written
124+
// during Step 2 or after), then the item will be decrypted client-side
125+
// and surfaced as a plaintext item.
126+
var key = new Dictionary<string, AttributeValue>
127+
{
128+
["partition_key"] = new AttributeValue { S = partitionKeyValue },
129+
["sort_key"] = new AttributeValue { N = sortKeyReadValue }
130+
};
143131

144-
var getResponse = await ddb.GetItemAsync(getRequest);
145-
Debug.Assert(getResponse.HttpStatusCode == HttpStatusCode.OK);
132+
var getRequest = new GetItemRequest
133+
{
134+
TableName = ddbTableName,
135+
Key = key,
136+
// In this example we configure a strongly consistent read
137+
// because we perform a read immediately after a write (for demonstrative purposes).
138+
// By default, reads are only eventually consistent.
139+
ConsistentRead = true
140+
};
146141

147-
// 8. Verify we get the expected item back
148-
if (getResponse.Item == null)
149-
{
150-
throw new Exception("No item found");
151-
}
142+
var getResponse = await ddb.GetItemAsync(getRequest);
143+
Debug.Assert(getResponse.HttpStatusCode == HttpStatusCode.OK);
152144

153-
bool success = MigrationUtils.VerifyReturnedItem(getResponse, partitionKeyValue, sortKeyReadValue);
154-
if (success)
155-
{
156-
Console.WriteLine("MigrationStep2 completed successfully");
157-
}
158-
return success;
145+
// 8. Verify we get the expected item back
146+
if (getResponse.Item == null)
147+
{
148+
throw new Exception("No item found");
159149
}
160-
catch (Exception e)
150+
151+
bool success = MigrationUtils.VerifyReturnedItem(getResponse, partitionKeyValue, sortKeyReadValue);
152+
if (success)
161153
{
162-
Console.WriteLine($"Error in MigrationStep2: {e.Message}");
163-
throw;
154+
Console.WriteLine("MigrationStep2 completed successfully");
164155
}
156+
return success;
165157
}
166158
}
167159
}

0 commit comments

Comments
 (0)