Skip to content

feat: immutable cryptographic materials (for keyrings) #231

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 12 commits into from
Mar 31, 2020
Merged

feat: immutable cryptographic materials (for keyrings) #231

merged 12 commits into from
Mar 31, 2020

Conversation

mattsb42-aws
Copy link
Member

Issue #, if available:

Description of changes:

The primary focus of this change is to move keyrings to immutable cryptographic materials. Rather than providing APIs that let you modify materials, we now provide APIs that let you get a new copy of those materials that also include additional contents.

While I was working on that, I found a few other points where the keyrings were not compliant with the spec, particularly around behavior when failing on encrypt and decrypt, and in the specific values set in the keyring trace. Looking back through the changes, I would have a hard time extracting any single piece, so unfortunately they're all just getting lumped into this one PR.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Check any applicable:

  • Were any files moved? Moving files changes their URL, which breaks all hyperlinks to the files.

@mattsb42-aws mattsb42-aws added this to the keyrings milestone Mar 27, 2020
@mattsb42-aws mattsb42-aws requested review from seebees, acioc, WesleyRosenblum and a team March 27, 2020 02:12
@@ -180,25 +181,26 @@ class _AwsKmsSingleCmkKeyring(Keyring):
def on_encrypt(self, encryption_materials):
# type: (EncryptionMaterials) -> EncryptionMaterials
trace_info = MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=self._key_id)
new_materials = copy.copy(encryption_materials)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it necessary to copy the materials?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not strictly necessary, but I think that having access to the original materials inside that scope could help with debugging if things aren't doing what people thing they should.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is a Python subtlety I'm missing, but aren't the original materials already available through the "encryption_materials" input?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flow is:

if no data key:
    data key, EDK = generate()
    new materials = materials(with data key)
else:
    EDK = encrypt(data key)

new materials = materials with data key(with EDK)

I went with that flow so that we could single-source the "with EDK" bit, but because of that, if we want to retain an available reference to the materials in the request we have a choice: we can either copy the request materials first:

copied materials = copy(request materials)

if no data key:
    data key, EDK = generate()
    copied materials = copied materials(with data key)
else:
    EDK = encrypt(data key)

copied materials = copied materials(with EDK)

or we can balance a null value

new materials = None

if no data key:
    data key, EDK = generate()
    new materials = request materials(with data key)
else:
    EDK = encrypt(data key)

if new materials is None:
    new materials = request materials(with EDK)
else:
    new materials = new materials(with EDK)

The copy flow seems cleaner to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work?

new materials = request materials

if no data key:
    data key, EDK = generate()
    new materials = new materials(with data key)
else:
    EDK = encrypt(data key)

new materials = new materials(with EDK)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess that would be fine. It feels less explicit, but since we're only ever using the immutable APIs it would effectively be doing the same thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's how I did it in Java, but I'll defer to your judgement on what you prefer for Python

@@ -5,6 +5,7 @@
.. versionadded:: 1.5.0

"""
import copy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you still need this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope! That'll be why CI is failing. :)

:rtype: EncryptionMaterials
"""
if encryption_materials.data_encryption_key is None:
_generate_data_key(encryption_materials=encryption_materials, key_provider=self._key_provider)
new_materials = copy.copy(encryption_materials)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new_materials = copy.copy(encryption_materials)
new_materials = encryption_materials

@@ -1,6 +1,7 @@
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Resources required for Multi Keyrings."""
import copy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants