def encrypt_decrypt(key_arn, source_plaintext, botocore_session=None):
    """Encrypts and then decrypts a string under one KMS customer master key (CMK).

    :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK
    :param bytes source_plaintext: Data to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    kwargs = dict(key_ids=[key_arn])

    if botocore_session is not None:
        kwargs["botocore_session"] = botocore_session

    # Set up an encryption client with an explicit commitment policy disallowing encryption with algorithms that
    # provide commitment
    client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)

    # Create master key provider using the ARN of the key and the session (botocore_session)
    kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kwargs)

    # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header. Note: in
    # order for decrypt to succeed, the key_ids value must be the key ARN of the CMK.
    ciphertext, encrypted_message_header = client.encrypt(source=source_plaintext, key_provider=kms_key_provider)

    # Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header
    plaintext, decrypted_message_header = client.decrypt(source=ciphertext, key_provider=kms_key_provider)

    # Verify that the original message and the decrypted message are the same
    assert source_plaintext == plaintext

    # Verify that the encryption context of the encrypted message and decrypted message match
    assert all(
        pair in encrypted_message_header.encryption_context.items()
        for pair in decrypted_message_header.encryption_context.items()
    )
Exemplo n.º 2
0
def encryptionSDKDemo():
    import aws_encryption_sdk
    from aws_encryption_sdk.identifiers import CommitmentPolicy

    #
    # Create AWS encryption sdk client with
    #
    client = aws_encryption_sdk.EncryptionSDKClient(
        commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)

    kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
        key_ids=[MASTER_KEY_ARN])

    #
    # My secret string
    #
    my_plaintext = b'This is some super secret data!'
    print(' Plain text to encrypt = %s \n ' % my_plaintext)

    #
    # Let's encrypt the plaintext data
    #
    print(" let's encrypt ! \n")
    my_ciphertext, encryptor_header = client.encrypt(
        source=my_plaintext, key_provider=kms_key_provider)
    print(' My ciphered text  = %s \n ' % my_ciphertext)

    #
    # Let's decrypt the ciphertext data
    #
    print(" let's decrypt ! \n")
    decrypted_plaintext, decryptor_header = client.decrypt(
        source=my_ciphertext, key_provider=kms_key_provider)
    print(' My ciphered text  decrypt = %s \n ' % decrypted_plaintext)
def initialize() -> DocumentBucketOperations:
    """
    Configure a Document Bucket API automatically with resources bootstrapped
    by CloudFormation.
    """
    # Load the pointers to CloudFormation resources that you just deployed
    state = toml.load(os.path.expanduser(
        config["base"]["state_file"]))["state"]

    # Now you have the identifiers of the CloudFormation resources loaded,
    # Set up your S3 Bucket for the Document Bucket
    bucket = boto3.resource("s3").Bucket(state["DocumentBucket"])
    # Set up your DynamoDB Table for the Document Bucket
    table = boto3.resource("dynamodb").Table(state["DocumentTable"])
    # Pull configuration of KMS resources
    faythe_cmk = state["FaytheCMK"]
    walter_cmk = state["WalterCMK"]
    # And the Master Key Provider configuring how to use KMS
    cmk = [faythe_cmk, walter_cmk]
    mkp = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=cmk)

    # Set up the API to interact with the Document Bucket using all these resources
    operations = DocumentBucketOperations(bucket, table, mkp)

    return operations
Exemplo n.º 4
0
def encrypt_decrypt(key_arns, source_plaintext, botocore_session=None):
    """Encrypts and then decrypts a string under two KMS customer master keys (CMK).

    :param str key_arns: Amazon Resource Names (ARNs) of the KMS CMKs
    :param bytes source_plaintext: Data to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    encrypt_kwargs = dict(key_ids=key_arns)

    if botocore_session is not None:
        encrypt_kwargs["botocore_session"] = botocore_session

    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create strict master key provider that is only allowed to encrypt and decrypt using the ARN of the provided key.
    strict_encrypt_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**encrypt_kwargs)

    # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header
    ciphertext, encrypted_message_header = client.encrypt(
        source=source_plaintext, key_provider=strict_encrypt_key_provider
    )

    # For each original master key, create a strict key provider that only lists that key and decrypt the encrypted
    # message using that provider. Note: in order for decrypt to succeed, the key_ids value must be the key ARN of the
    # CMK.
    for key_arn in key_arns:
        decrypt_kwargs = dict(key_ids=[key_arn])
        if botocore_session is not None:
            encrypt_kwargs["botocore_session"] = botocore_session

        strict_decrypt_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**decrypt_kwargs)
        plaintext, decrypted_message_header = client.decrypt(
            source=ciphertext, key_provider=strict_decrypt_key_provider
        )

        # Verify that the original message and the decrypted message are the same
        assert source_plaintext == plaintext

        # Verify that the encryption context of the encrypted message and decrypted message match
        assert all(
            pair in encrypted_message_header.encryption_context.items()
            for pair in decrypted_message_header.encryption_context.items()
        )
Exemplo n.º 5
0
def encrypt_decrypt_stream(key_arn,
                           source_plaintext_filename,
                           botocore_session=None):
    """Encrypts and then decrypts streaming data under one KMS customer master key (CMK).

    :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK
    :param str source_plaintext_filename: Filename of file to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    kwargs = dict()

    kwargs["key_ids"] = [key_arn]

    if botocore_session is not None:
        kwargs["botocore_session"] = botocore_session

    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(
        commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create master key provider using the ARN of the key and the session (botocore_session)
    kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
        **kwargs)

    ciphertext_filename = source_plaintext_filename + ".encrypted"
    decrypted_text_filename = source_plaintext_filename + ".decrypted"

    # Encrypt the plaintext using the AWS Encryption SDK.
    with open(source_plaintext_filename,
              "rb") as plaintext, open(ciphertext_filename,
                                       "wb") as ciphertext:
        with client.stream(source=plaintext,
                           mode="e",
                           key_provider=kms_key_provider) as encryptor:
            for chunk in encryptor:
                ciphertext.write(chunk)

    # Decrypt the encrypted message using the AWS Encryption SDK.
    with open(ciphertext_filename,
              "rb") as ciphertext, open(decrypted_text_filename,
                                        "wb") as plaintext:
        with client.stream(source=ciphertext,
                           mode="d",
                           key_provider=kms_key_provider) as decryptor:
            for chunk in decryptor:
                plaintext.write(chunk)

    # Check if the original message and the decrypted message are the same
    assert filecmp.cmp(source_plaintext_filename, decrypted_text_filename)

    # Check if the headers of the encrypted message and decrypted message match
    assert all(pair in encryptor.header.encryption_context.items()
               for pair in decryptor.header.encryption_context.items())
    return ciphertext_filename, decrypted_text_filename
def encrypt_with_caching(kms_cmk_arn, max_age_in_cache, cache_capacity):
    """Encrypts a string using an AWS KMS customer master key (CMK) and data key caching.

    :param str kms_cmk_arn: Amazon Resource Name (ARN) of the KMS customer master key
    :param float max_age_in_cache: Maximum time in seconds that a cached entry can be used
    :param int cache_capacity: Maximum number of entries to retain in cache at once
    """
    # Data to be encrypted
    my_data = "My plaintext data"

    # Security thresholds
    #   Max messages (or max bytes per) data key are optional
    MAX_ENTRY_MESSAGES = 100

    # Create an encryption context
    encryption_context = {"purpose": "test"}

    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create a master key provider for the KMS customer master key (CMK)
    key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_cmk_arn])

    # Create a local cache
    cache = aws_encryption_sdk.LocalCryptoMaterialsCache(cache_capacity)

    # Create a caching CMM
    caching_cmm = aws_encryption_sdk.CachingCryptoMaterialsManager(
        master_key_provider=key_provider,
        cache=cache,
        max_age=max_age_in_cache,
        max_messages_encrypted=MAX_ENTRY_MESSAGES,
    )

    # When the call to encrypt data specifies a caching CMM,
    # the encryption operation uses the data key cache specified
    # in the caching CMM
    encrypted_message, _header = client.encrypt(
        source=my_data, materials_manager=caching_cmm, encryption_context=encryption_context
    )

    return encrypted_message
Exemplo n.º 7
0
def encrypt_decrypt(key_arn, source_plaintext, botocore_session=None):
    """Encrypts a string under one KMS customer master key (CMK), then decrypts it using discovery mode.

    :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK
    :param bytes source_plaintext: Data to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    encrypt_kwargs = dict(key_ids=[key_arn])

    if botocore_session is not None:
        encrypt_kwargs["botocore_session"] = botocore_session

    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create strict master key provider that is only allowed to encrypt and decrypt using the ARN of the provided key.
    strict_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**encrypt_kwargs)

    # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header
    ciphertext, encrypted_message_header = client.encrypt(source=source_plaintext, key_provider=strict_key_provider)

    # Create a second master key provider in discovery mode that does not explicitly list the key used to encrypt.
    # Note: The discovery_filter argument is optional; if you omit this, the AWS Encryption SDK attempts to
    # decrypt any ciphertext it receives.
    arn = arn_from_str(key_arn)
    decrypt_kwargs = dict(discovery_filter=DiscoveryFilter(account_ids=[arn.account_id], partition=arn.partition))
    if botocore_session is not None:
        encrypt_kwargs["botocore_session"] = botocore_session
    discovery_key_provider = aws_encryption_sdk.DiscoveryAwsKmsMasterKeyProvider(**decrypt_kwargs)

    # Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header.
    plaintext, decrypted_message_header = client.decrypt(source=ciphertext, key_provider=discovery_key_provider)

    # Verify that the original message and the decrypted message are the same
    assert source_plaintext == plaintext

    # Verify that the encryption context of the encrypted message and decrypted message match
    assert all(
        pair in encrypted_message_header.encryption_context.items()
        for pair in decrypted_message_header.encryption_context.items()
    )
def cycle_string(key_arn, source_plaintext, botocore_session=None):
    """Encrypts and then decrypts a string under a KMS customer master key (CMK).

    :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK
    :param bytes source_plaintext: Data to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(
        commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create a KMS master key provider
    kms_kwargs = dict(key_ids=[key_arn])
    if botocore_session is not None:
        kms_kwargs["botocore_session"] = botocore_session
    master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
        **kms_kwargs)

    # Encrypt the plaintext source data
    ciphertext, encryptor_header = client.encrypt(
        source=source_plaintext, key_provider=master_key_provider)

    # Decrypt the ciphertext
    cycled_plaintext, decrypted_header = client.decrypt(
        source=ciphertext, key_provider=master_key_provider)

    # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext
    assert cycled_plaintext == source_plaintext

    # Verify that the encryption context used in the decrypt operation includes all key pairs from
    # the encrypt operation. (The SDK can add pairs, so don't require an exact match.)
    #
    # In production, always use a meaningful encryption context. In this sample, we omit the
    # encryption context (no key pairs).
    assert all(pair in decrypted_header.encryption_context.items()
               for pair in encryptor_header.encryption_context.items())
Exemplo n.º 9
0
def test_encrypted_payload_coding():
    key_id = os.environ['KEY_ID']
    session = boto3.Session()

    mkp = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
        key_ids=[key_id], botocore_session=session._session)

    payload = {
        'iss': 'issuer',
        'iat': 0,
        'tid': 'asdf',
        'exp': 0,
        'token': 'jkljkl',
        'action': {
            'name': 'foo',
            'type': 'success',
            'output': {}
        },
        'param': False,
    }

    validate_payload_schema(payload)

    encoded_payload = encode_payload(payload, mkp)
    assert encoded_payload.startswith('2-')
    decoded_payload = decode_payload(encoded_payload, mkp)
    validate_payload_schema(decoded_payload)
    assert_dicts_equal(payload, decoded_payload)

    encoded_payload = encode_payload(payload, None)
    assert encoded_payload.startswith('1-')
    with pytest.raises(EncryptionRequired):
        decoded_payload = decode_payload(encoded_payload, mkp)

    encoded_payload = encode_payload(payload, mkp)
    assert encoded_payload.startswith('2-')
    with pytest.raises(DecryptionUnsupported):
        decoded_payload = decode_payload(encoded_payload, None)
def cycle_file(key_arn, source_plaintext_filename, botocore_session=None):
    """Encrypts and then decrypts a file using a KMS master key provider and a custom static master
    key provider. Both master key providers are used to encrypt the plaintext file, so either one alone
    can decrypt it.

    :param str key_arn: Amazon Resource Name (ARN) of the KMS Customer Master Key (CMK)
    (http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html)
    :param str source_plaintext_filename: Filename of file to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    # "Cycled" means encrypted and then decrypted
    ciphertext_filename = source_plaintext_filename + ".encrypted"
    cycled_kms_plaintext_filename = source_plaintext_filename + ".kms.decrypted"
    cycled_static_plaintext_filename = source_plaintext_filename + ".static.decrypted"

    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(
        commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create a KMS master key provider
    kms_kwargs = dict(key_ids=[key_arn])
    if botocore_session is not None:
        kms_kwargs["botocore_session"] = botocore_session
    kms_master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
        **kms_kwargs)

    # Create a static master key provider and add a master key to it
    static_key_id = os.urandom(8)
    static_master_key_provider = StaticRandomMasterKeyProvider()
    static_master_key_provider.add_master_key(static_key_id)

    # Add the static master key provider to the AWS KMS master key provider
    #   The resulting master key provider uses AWS KMS master keys to generate (and encrypt)
    #   data keys and static master keys to create an additional encrypted copy of each data key.
    kms_master_key_provider.add_master_key_provider(static_master_key_provider)

    # Encrypt plaintext with both AWS KMS and static master keys
    with open(source_plaintext_filename,
              "rb") as plaintext, open(ciphertext_filename,
                                       "wb") as ciphertext:
        with client.stream(source=plaintext,
                           mode="e",
                           key_provider=kms_master_key_provider) as encryptor:
            for chunk in encryptor:
                ciphertext.write(chunk)

    # Decrypt the ciphertext with only the AWS KMS master key
    with open(ciphertext_filename,
              "rb") as ciphertext, open(cycled_kms_plaintext_filename,
                                        "wb") as plaintext:
        with client.stream(
                source=ciphertext,
                mode="d",
                key_provider=aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
                    **kms_kwargs)) as kms_decryptor:
            for chunk in kms_decryptor:
                plaintext.write(chunk)

    # Decrypt the ciphertext with only the static master key
    with open(ciphertext_filename,
              "rb") as ciphertext, open(cycled_static_plaintext_filename,
                                        "wb") as plaintext:
        with client.stream(
                source=ciphertext,
                mode="d",
                key_provider=static_master_key_provider) as static_decryptor:
            for chunk in static_decryptor:
                plaintext.write(chunk)

    # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext
    assert filecmp.cmp(source_plaintext_filename,
                       cycled_kms_plaintext_filename)
    assert filecmp.cmp(source_plaintext_filename,
                       cycled_static_plaintext_filename)

    # Verify that the encryption context in the decrypt operation includes all key pairs from the
    # encrypt operation.
    #
    # In production, always use a meaningful encryption context. In this sample, we omit the
    # encryption context (no key pairs).
    assert all(pair in kms_decryptor.header.encryption_context.items()
               for pair in encryptor.header.encryption_context.items())
    assert all(pair in static_decryptor.header.encryption_context.items()
               for pair in encryptor.header.encryption_context.items())
    return (ciphertext_filename, cycled_kms_plaintext_filename,
            cycled_static_plaintext_filename)
Exemplo n.º 11
0
                                      get_force_disable_parameters,
                                      get_disable_post_actions, is_verbose,
                                      get_header)

from sfn_callback_urls.exceptions import (ReturnHttpResponse, BaseError,
                                          ActionMismatched, ParametersDisabled,
                                          PostActionsDisabled,
                                          InvalidPostActionBody,
                                          StepFunctionsError)

BOTO3_SESSION = boto3.Session()
STEP_FUNCTIONS_CLIENT = BOTO3_SESSION.client('stepfunctions')
MASTER_KEY_PROVIDER = None
if 'KEY_ID' in os.environ:
    MASTER_KEY_PROVIDER = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
        key_ids=[os.environ['KEY_ID']],
        botocore_session=BOTO3_SESSION._session)


def handler(request, context):
    if is_verbose():
        print(f'Request: {json.dumps(request)}')

    timestamp = datetime.datetime.now()

    log_event = {
        'timestamp': timestamp.isoformat(),
    }

    try:
        response = OrderedDict(
Exemplo n.º 12
0
import boto3
import time
import requests
import json
import os
import aws_encryption_sdk
from aws_encryption_sdk import CommitmentPolicy
from DelaySayExceptions import UserAuthorizeError
from datetime import timezone, timedelta

encryption_client = aws_encryption_sdk.EncryptionSDKClient(
    commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)
kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(
    key_ids=[os.environ['KMS_MASTER_KEY_ARN']])

# This is the format used to log dates in the DynamoDB table.
DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"


def encrypt_oauth_token(token):
    token_as_bytes = token.encode()
    encrypted_token, encryptor_header = encryption_client.encrypt(
        source=token_as_bytes, key_provider=kms_key_provider)
    return encrypted_token


def decrypt_oauth_token(encrypted_token):
    token_as_bytes, decryptor_header = encryption_client.decrypt(
        source=encrypted_token, key_provider=kms_key_provider)
    token = token_as_bytes.decode()
    return token
Exemplo n.º 13
0
import aws_encryption_sdk

kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[
    'arn:aws:kms:us-east-1:873559269338:key/1e1a6a81-93e0-4b9a-954b-cc09802bf3ce'
])
my_plaintext = 'This is some super secret data!  Yup, sure is!'

client = aws_encryption_sdk.EncryptionSDKClient(
    commitment_policy=aws_encryption_sdk.CommitmentPolicy.
    FORBID_ENCRYPT_ALLOW_DECRYPT, )

my_ciphertext, encryptor_header = client.encrypt(source=my_plaintext,
                                                 key_provider=kms_key_provider)

decrypted_plaintext, decryptor_header = client.decrypt(
    source=my_ciphertext, key_provider=kms_key_provider)

assert my_plaintext == decrypted_plaintext.decode('ascii')
assert encryptor_header.encryption_context == decryptor_header.encryption_context