-
Notifications
You must be signed in to change notification settings - Fork 86
docs: add example to replicate AWS KMS MKP behavior with AWS KMS keyring #255
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
Changes from 6 commits
314323e
356083d
3c71661
b0c0cc0
93a1371
70134b1
dc8dd2f
0181431
2aed0c8
bbb24ef
b7ced3d
6239257
52d6277
8837284
b3598d3
86f618b
52cbca6
a57c379
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,88 @@ | ||||||||||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||||||||||
# SPDX-License-Identifier: Apache-2.0 | ||||||||||
""" | ||||||||||
Before there were keyrings, there were master key providers. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once upon a time ... :)
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
Master key providers were the original configuration structure | ||||||||||
that we provided for defining how you want to protect your data keys. | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
The AWS KMS master key provider was the tool that we provided for interacting with AWS KMS. | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
Like the AWS KMS keyring, | ||||||||||
the AWS KMS master key provider encrypts with all CMKs that you identify, | ||||||||||
but unlike the AWS KMS keyring, | ||||||||||
the AWS KMS master key provider always attempts to decrypt | ||||||||||
*any* data keys that were encrypted under an AWS KMS CMK. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
-or-
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not quite what I was getting at. Whether or not it can decrypt depends on the KMS/IAM permissions. Just like the discovery keyring, the point I was trying to make is that it does in fact reach out to the KMS service for every KMS-encrypted EDK whether or not it succeeds. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The difficulty here is the combination of "always" and "any." Does the ESDK always attempt to decrypt all of the encrypted data keys in an encrypted message? Or, it can attempt to decrypt any of them? |
||||||||||
We have found that separating these two behaviors | ||||||||||
makes it more clear what behavior to expect, | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
so that is what we did with the AWS KMS keyring and the AWS KMS discovery keyring. | ||||||||||
However, as you migrate away from master key providers to keyrings, | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
you might need to replicate the behavior of the AWS KMS master key provider. | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
This example shows how to configure a keyring that behaves like an AWS KMS master key provider. | ||||||||||
|
||||||||||
For more examples of how to use the AWS KMS keyring, | ||||||||||
see the ``keyring/aws_kms`` directory. | ||||||||||
""" | ||||||||||
import aws_encryption_sdk | ||||||||||
from aws_encryption_sdk.key_providers.kms import KMSMasterKeyProvider | ||||||||||
from aws_encryption_sdk.keyrings.aws_kms import AwsKmsKeyring | ||||||||||
from aws_encryption_sdk.keyrings.multi import MultiKeyring | ||||||||||
|
||||||||||
|
||||||||||
def run(aws_kms_cmk, source_plaintext): | ||||||||||
# type: (str, bytes) -> None | ||||||||||
"""Demonstrate how to create a keyring that behaves like an AWS KMS master key provider. | ||||||||||
|
||||||||||
:param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
:param bytes source_plaintext: Plaintext to encrypt | ||||||||||
""" | ||||||||||
# Prepare your encryption context. | ||||||||||
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context | ||||||||||
encryption_context = { | ||||||||||
"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", | ||||||||||
} | ||||||||||
|
||||||||||
# This is the master key provider whose behavior we want to replicate. | ||||||||||
# | ||||||||||
# On encrypt, this master key provider only uses the single target AWS KMS CMK. | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
# However, on decrypt, this master key provider attempts to decrypt | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
# any data keys that were encrypted under an AWS KMS CMK. | ||||||||||
_master_key_provider_to_replicate = KMSMasterKeyProvider(key_ids=[aws_kms_cmk]) # noqa: intentionally never used | ||||||||||
|
||||||||||
# Create a keyring that encrypts and decrypts using a single AWS KMS CMK. | ||||||||||
single_cmk_keyring = AwsKmsKeyring(generator_key_id=aws_kms_cmk) | ||||||||||
|
||||||||||
# Create an AWS KMS discovery keyring that will attempt to decrypt | ||||||||||
# any data keys that were encrypted under an AWS KMS CMK. | ||||||||||
discovery_keyring = AwsKmsKeyring(is_discovery=True) | ||||||||||
|
||||||||||
# Combine the single-CMK and discovery keyrings | ||||||||||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
# to create a keyring that behaves like an AWS KMS master key provider. | ||||||||||
keyring = MultiKeyring(generator=single_cmk_keyring, children=[discovery_keyring]) | ||||||||||
|
||||||||||
# Encrypt your plaintext data. | ||||||||||
ciphertext, _encrypt_header = aws_encryption_sdk.encrypt( | ||||||||||
source=source_plaintext, encryption_context=encryption_context, keyring=keyring | ||||||||||
) | ||||||||||
|
||||||||||
# Demonstrate that the ciphertext and plaintext are different. | ||||||||||
assert ciphertext != source_plaintext | ||||||||||
|
||||||||||
# Decrypt your encrypted data using the same keyring you used on encrypt. | ||||||||||
# | ||||||||||
# You do not need to specify the encryption context on decrypt | ||||||||||
# because the header of the encrypted message includes the encryption context. | ||||||||||
decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, keyring=keyring) | ||||||||||
|
||||||||||
# Demonstrate that the decrypted plaintext is identical to the original plaintext. | ||||||||||
assert decrypted == source_plaintext | ||||||||||
|
||||||||||
# Verify that the encryption context used in the decrypt operation includes | ||||||||||
# the encryption context that you specified when encrypting. | ||||||||||
# The AWS Encryption SDK can add pairs, so don't require an exact match. | ||||||||||
# | ||||||||||
# In production, always use a meaningful encryption context. | ||||||||||
assert set(encryption_context.items()) <= set(decrypt_header.encryption_context.items()) |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use "reproduce" instead of "replicate?" The KMS is using "replicate" and "replica" for other purposes. Although most people won't notice, I can envisions someone with limited English language skills googling this and becoming hopelessly confused.