-
Notifications
You must be signed in to change notification settings - Fork 26
chore: add KMS Keyring example in an multithreaded environment #735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
aca5a42
Add multithreading test
rishav-karanjit 789a42f
auto commit
rishav-karanjit b197285
Update AwsEncryptionSDK/runtimes/go/examples/utils/exampleUtils.go
rishav-karanjit 4d612fa
auto commit
rishav-karanjit c885592
Ohh no its 5
rishav-karanjit 2a0e462
Revert "Ohh no its 5"
rishav-karanjit 88f5a3c
Add a comment
rishav-karanjit fb0a657
nit
rishav-karanjit File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 193 additions & 0 deletions
193
AwsEncryptionSDK/runtimes/go/examples/multithreading/awskmskeyring.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| /* | ||
| This example sets up the AWS KMS Keyring in an multithreaded environment. | ||
| The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and | ||
| decrypt data keys. This example creates a KMS Keyring and then encrypts a custom input exampleText | ||
| with an encryption context. This example also includes some sanity checks for demonstration: | ||
| 1. Ciphertext and plaintext data are not the same | ||
| 2. Decrypted plaintext value matches exampleText | ||
| These sanity checks are for demonstration in the example only. You do not need these in your code. | ||
| AWS KMS keyrings can be used independently or in a multi-keyring with other keyrings | ||
| of the same or a different type. | ||
| For more information on how to use KMS keyrings, see | ||
| https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html | ||
| For more information on KMS Key identifiers, see | ||
| https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id | ||
| */ | ||
|
|
||
| package multithreading | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "sync" | ||
|
|
||
| mpl "github.com/aws/aws-cryptographic-material-providers-library/mpl/awscryptographymaterialproviderssmithygenerated" | ||
| mpltypes "github.com/aws/aws-cryptographic-material-providers-library/mpl/awscryptographymaterialproviderssmithygeneratedtypes" | ||
| client "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygenerated" | ||
| esdktypes "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygeneratedtypes" | ||
| "github.com/aws/aws-sdk-go-v2/config" | ||
| "github.com/aws/aws-sdk-go-v2/service/kms" | ||
| ) | ||
|
|
||
| // Function to handle encryption | ||
| func encryptData( | ||
| ctx context.Context, | ||
| encryptionClient *client.Client, | ||
| plaintext string, | ||
| encryptionContext map[string]string, | ||
| keyring mpltypes.IKeyring) (*esdktypes.EncryptOutput, error) { | ||
| res, err := encryptionClient.Encrypt(ctx, esdktypes.EncryptInput{ | ||
| Plaintext: []byte(plaintext), | ||
| EncryptionContext: encryptionContext, | ||
| Keyring: keyring, | ||
| }) | ||
| return res, err | ||
| } | ||
|
|
||
| // Function to handle decryption | ||
| func decryptData( | ||
| ctx context.Context, | ||
| encryptionClient *client.Client, | ||
| ciphertext []byte, | ||
| encryptionContext map[string]string, | ||
| keyring mpltypes.IKeyring) (*esdktypes.DecryptOutput, error) { | ||
| res, err := encryptionClient.Decrypt(ctx, esdktypes.DecryptInput{ | ||
| EncryptionContext: encryptionContext, | ||
| Keyring: keyring, | ||
| Ciphertext: ciphertext, | ||
| }) | ||
| return res, err | ||
| } | ||
|
|
||
| func processEncryptionWorker( | ||
| ctx context.Context, | ||
| wg *sync.WaitGroup, | ||
| jobs <-chan string, | ||
| encryptionClient *client.Client, | ||
| awsKmsKeyring mpltypes.IKeyring, | ||
| encryptionContext map[string]string, | ||
| ) { | ||
| defer wg.Done() | ||
| for plaintext := range jobs { | ||
| // Perform encryption | ||
| encryptResult, err := encryptData( | ||
| ctx, | ||
| encryptionClient, | ||
| plaintext, | ||
| encryptionContext, | ||
| awsKmsKeyring) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| // Verify ciphertext is different from plaintext | ||
| if string(encryptResult.Ciphertext) == plaintext { | ||
| panic("Ciphertext and Plaintext before encryption are the same") | ||
| } | ||
| // Perform decryption | ||
| decryptResult, err := decryptData( | ||
| ctx, | ||
| encryptionClient, | ||
| encryptResult.Ciphertext, | ||
| encryptionContext, | ||
| awsKmsKeyring, | ||
| ) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| // If you do not specify the encryption context on Decrypt, it's recommended to check if the resulting encryption context matches. | ||
| // The encryption context was specified on decrypt; we are validating the encryption context for demonstration only. | ||
| // Before your application uses plaintext data, verify that the encryption context that | ||
| // you used to encrypt the message is included in the encryption context that was used to | ||
| // decrypt the message. The AWS Encryption SDK can add pairs, so don't require an exact match. | ||
| if err := validateEncryptionContext(encryptionContext, decryptResult.EncryptionContext); err != nil { | ||
| panic(err) | ||
| } | ||
| if string(decryptResult.Plaintext) != plaintext { | ||
| panic("Plaintext after decryption and Plaintext before encryption are NOT the same") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func AWSKMSMultiThreadTest(texts []string, defaultKmsKeyID, defaultKmsKeyRegion string) { | ||
| // Create the AWS KMS client | ||
| cfg, err := config.LoadDefaultConfig(context.TODO()) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| kmsClient := kms.NewFromConfig(cfg, func(o *kms.Options) { | ||
| o.Region = defaultKmsKeyRegion | ||
| }) | ||
| // Initialize the mpl client | ||
| matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{}) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| // Create the keyring | ||
| ctx := context.Background() | ||
| awsKmsKeyringInput := mpltypes.CreateAwsKmsKeyringInput{ | ||
| KmsClient: kmsClient, | ||
| KmsKeyId: defaultKmsKeyID, | ||
| } | ||
| awsKmsKeyring, err := matProv.CreateAwsKmsKeyring(ctx, awsKmsKeyringInput) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| // Instantiate the encryption SDK client. | ||
| // This builds the default client with the RequireEncryptRequireDecrypt commitment policy, | ||
| // which enforces that this client only encrypts using committing algorithm suites and enforces | ||
| // that this client will only decrypt encrypted messages that were created with a committing | ||
| // algorithm suite. | ||
| encryptionClient, err := client.NewClient(esdktypes.AwsEncryptionSdkConfig{}) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| // Create your encryption context (Optional). | ||
| // Remember that your encryption context is NOT SECRET. | ||
| // https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context | ||
| encryptionContext := map[string]string{ | ||
| "encryption": "context", | ||
| "is not": "secret", | ||
| "but adds": "useful metadata", | ||
| "that can help you": "be confident that", | ||
| "the data you are handling": "is what you think it is", | ||
| } | ||
| // Create buffered channels to handle multiple operations | ||
| // As an example, we will have 10 workers, adjust this number as needed. | ||
| numWorkers := 10 | ||
|
|
||
| // Create a wait group to track all goroutines | ||
| var wg sync.WaitGroup | ||
|
|
||
| // Create a channel to send a plaintext | ||
| jobs := make(chan string, len(texts)) | ||
|
|
||
| // Start worker pool | ||
| for range numWorkers { | ||
| wg.Add(1) | ||
| go processEncryptionWorker(ctx, &wg, jobs, encryptionClient, awsKmsKeyring, encryptionContext) | ||
| } | ||
|
|
||
| // Send jobs to workers | ||
| for _, text := range texts { | ||
| jobs <- text | ||
| } | ||
| close(jobs) | ||
| // Wait for all workers to complete | ||
| wg.Wait() | ||
| fmt.Println("AWS KMS Keyring example in multithreaded environment completed successfully.") | ||
| } | ||
|
|
||
| // This function only does subset matching because AWS Encryption SDK can add pairs, so don't require an exact match. | ||
| func validateEncryptionContext(expected, actual map[string]string) error { | ||
| for expectedKey, expectedValue := range expected { | ||
| actualValue, exists := actual[expectedKey] | ||
| if !exists || actualValue != expectedValue { | ||
| return fmt.Errorf("encryption context mismatch: expected key '%s' with value '%s'", | ||
| expectedKey, expectedValue) | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.