diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..2e4b88ed0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,36 @@ +sudo: false +language: python +matrix: + include: + - python: 2.7 + env: TOXENV=py27 + - python: 3.4 + env: TOXENV=py34 + - python: 3.5 + env: TOXENV=py35 + - python: 3.6 + env: TOXENV=py36 + - python: 3.6 + env: TOXENV=bandit + - python: 3.6 + env: TOXENV=doc8 + - python: 3.6 + env: TOXENV=readme +# pending reorg of deserialize_header +# - python: 3.6 +# env: TOXENV=flake8 +# - python: 3.6 +# env: TOXENV=pylint +# pending test-vectors refactor +# - python: 3.6 +# env: TOXENV=flake8-tests + - python: 3.6 + env: TOXENV=pylint-tests + - python: 3.6 + env: TOXENV=examples + - python: 3.6 + env: TOXENV=flake8-examples + - python: 3.6 + env: TOXENV=pylint-examples +install: pip install tox +script: tox \ No newline at end of file diff --git a/README.rst b/README.rst index dc74097bf..30c69033b 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,17 @@ aws-encryption-sdk ################## +.. image:: https://img.shields.io/pypi/v/aws-encryption-sdk.svg + :target: https://pypi.python.org/pypi/aws-encryption-sdk + :alt: Latest Version + +.. image:: https://readthedocs.org/projects/aws-encryption-sdk-python/badge/ + :target: https://aws-encryption-sdk-python.readthedocs.io/en/stable/ + :alt: Documentation Status + +.. image:: https://travis-ci.org/awslabs/aws-encryption-sdk-python.svg?branch=master + :target: https://travis-ci.org/awslabs/aws-encryption-sdk-python + The AWS Encryption SDK for Python provides a fully compliant, native Python implementation of the `AWS Encryption SDK`_. The latest full documentation can be found at `Read the Docs`_. diff --git a/examples/test/test_i_basic_encryption.py b/examples/test/test_i_basic_encryption.py index d83e1fa63..9de73741d 100644 --- a/examples/test/test_i_basic_encryption.py +++ b/examples/test/test_i_basic_encryption.py @@ -19,20 +19,17 @@ ]) from basic_encryption import cycle_string -from integration_test_utils import ( - get_cmk_arn, read_test_config, setup_botocore_session, SKIP_MESSAGE, skip_tests -) +import botocore.session +from integration_test_utils import get_cmk_arn, SKIP_MESSAGE, skip_tests import pytest @pytest.mark.skipif(skip_tests(), reason=SKIP_MESSAGE) def test_cycle_string(): plaintext = os.urandom(1024) - config = read_test_config() - cmk_arn = get_cmk_arn(config) - botocore_session = setup_botocore_session(config) + cmk_arn = get_cmk_arn() cycle_string( key_arn=cmk_arn, source_plaintext=plaintext, - botocore_session=botocore_session + botocore_session=botocore.session.Session() ) diff --git a/examples/test/test_i_basic_file_encryption_with_multiple_providers.py b/examples/test/test_i_basic_file_encryption_with_multiple_providers.py index 902a8dea5..6b3e08340 100644 --- a/examples/test/test_i_basic_file_encryption_with_multiple_providers.py +++ b/examples/test/test_i_basic_file_encryption_with_multiple_providers.py @@ -20,17 +20,14 @@ import tempfile from basic_file_encryption_with_multiple_providers import cycle_file -from integration_test_utils import ( - get_cmk_arn, read_test_config, setup_botocore_session, SKIP_MESSAGE, skip_tests -) +import botocore.session +from integration_test_utils import get_cmk_arn, SKIP_MESSAGE, skip_tests import pytest @pytest.mark.skipif(skip_tests(), reason=SKIP_MESSAGE) def test_cycle_file(): - config = read_test_config() - cmk_arn = get_cmk_arn(config) - botocore_session = setup_botocore_session(config) + cmk_arn = get_cmk_arn() _handle, filename = tempfile.mkstemp() with open(filename, 'wb') as f: f.write(os.urandom(1024)) @@ -38,7 +35,7 @@ def test_cycle_file(): new_files = cycle_file( key_arn=cmk_arn, source_plaintext_filename=filename, - botocore_session=botocore_session + botocore_session=botocore.session.Session() ) for f in new_files: os.remove(f) diff --git a/examples/test/test_i_data_key_caching_basic.py b/examples/test/test_i_data_key_caching_basic.py index 5da304d65..2b4d441dc 100644 --- a/examples/test/test_i_data_key_caching_basic.py +++ b/examples/test/test_i_data_key_caching_basic.py @@ -19,14 +19,13 @@ ]) from data_key_caching_basic import encrypt_with_caching -from integration_test_utils import get_cmk_arn, read_test_config, SKIP_MESSAGE, skip_tests +from integration_test_utils import get_cmk_arn, SKIP_MESSAGE, skip_tests import pytest @pytest.mark.skipif(skip_tests(), reason=SKIP_MESSAGE) def test_encrypt_with_caching(): - config = read_test_config() - cmk_arn = get_cmk_arn(config) + cmk_arn = get_cmk_arn() encrypt_with_caching( kms_cmk_arn=cmk_arn, max_age_in_cache=10.0, diff --git a/test/integration/README b/test/integration/README deleted file mode 100644 index 2af8a1fd2..000000000 --- a/test/integration/README +++ /dev/null @@ -1,5 +0,0 @@ -To set up the integration test: -1) Copy test_values_template.conf to test_values.conf -2) Make sure that all fields in test_values.conf are populated with accurate values - * NOTE: AWS credentials are optional; if they are not found, the standard AWS credential sources are used. -3) Set environment variable AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_CONTROL='RUN' \ No newline at end of file diff --git a/test/integration/README.rst b/test/integration/README.rst new file mode 100644 index 000000000..84d64a888 --- /dev/null +++ b/test/integration/README.rst @@ -0,0 +1,13 @@ +************************************ +aws-encryption-sdk Integration Tests +************************************ + +In order to run these integration tests successfully, these things must be configured. + +#. Ensure that AWS credentials are available in one of the `automatically discoverable credential locations`_. +#. Set environment variable ``AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID`` to valid + `AWS KMS key id`_ to use for integration tests. +#. Set environment variable ``AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_CONTROL`` to ``RUN``. + +.. _automatically discoverable credential locations: http://boto3.readthedocs.io/en/latest/guide/configuration.html +.. _AWS KMS key id: http://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html diff --git a/test/integration/integration_test_utils.py b/test/integration/integration_test_utils.py index 541d06b85..e3f51de8a 100644 --- a/test/integration/integration_test_utils.py +++ b/test/integration/integration_test_utils.py @@ -14,60 +14,31 @@ decision making for integration tests.""" import os -import botocore.session -from six.moves.configparser import ConfigParser from aws_encryption_sdk.key_providers.kms import KMSMasterKeyProvider -SKIP_MESSAGE = 'Skipping tests due to blocking environment variable' +SKIP_MESSAGE = ( + 'Required environment variables not found. Skipping integration tests.' + ' See integration tests README.rst for more information.' +) +TEST_CONTROL = 'AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_CONTROL' +AWS_KMS_KEY_ID = 'AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID' def skip_tests(): - blocker_var_name = 'AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_CONTROL' - blocker_val = os.environ.get(blocker_var_name, None) - if blocker_val != 'RUN': - return True - return False + """Only run tests if both required environment variables are found.""" + test_control = os.environ.get(TEST_CONTROL, None) + key_id = os.environ.get(AWS_KMS_KEY_ID, None) + return not (test_control == 'RUN' and key_id is not None) -def read_test_config(): - """Reads the test_values config file.""" - config = ConfigParser() - config_file = os.sep.join([os.path.dirname(__file__), 'test_values.conf']) - config_readme = os.sep.join([os.path.dirname(__file__), 'README']) - if not os.path.isfile(config_file): - raise Exception('Integration test config file missing. See setup instructions in {}'.format(config_readme)) - config.read(config_file) - return config - - -def get_cmk_arn(config): - """Retrieves the target CMK ARN from the received config.""" - return config.get('TestKMSThickClientIntegration', 'cmk_arn') - - -def setup_botocore_session(config): - """Configures a botocore session based on the received config.""" - aws_params = {} - for key in ['aws_access_key_id', 'aws_secret_access_key', 'aws_session_token']: - try: - aws_params[key] = config.get('TestKMSThickClientIntegration', key) - except Exception: - pass - botocore_session = botocore.session.Session() - if aws_params: - botocore_session.set_credentials( - access_key=aws_params['aws_access_key_id'], - secret_key=aws_params['aws_secret_access_key'], - token=aws_params['aws_session_token'] - ) - return botocore_session +def get_cmk_arn(): + """Retrieves the target CMK ARN from environment variable.""" + return os.environ.get(AWS_KMS_KEY_ID) def setup_kms_master_key_provider(): """Reads the test_values config file and builds the requested KMS Master Key Provider.""" - config = read_test_config() - cmk_arn = get_cmk_arn(config) - botocore_session = setup_botocore_session(config) - kms_master_key_provider = KMSMasterKeyProvider(botocore_session=botocore_session) + cmk_arn = get_cmk_arn() + kms_master_key_provider = KMSMasterKeyProvider() kms_master_key_provider.add_master_key(cmk_arn) return kms_master_key_provider diff --git a/test/integration/test_values_template.conf b/test/integration/test_values_template.conf deleted file mode 100644 index daab73d7a..000000000 --- a/test/integration/test_values_template.conf +++ /dev/null @@ -1,5 +0,0 @@ -[TestKMSThickClientIntegration] -aws_access_key_id= -aws_secret_access_key= -aws_session_token= -cmk_arn= diff --git a/tox.ini b/tox.ini index 2fd5b17a3..a9e30b5c8 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,16 @@ envlist = # linters-examples :: Runs all linters over all examples and examples tests. [testenv] -passenv = AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_CONTROL +# _TEST_CONTROL : +# _AWS_KMS_KEY_ID : +# AWS_ACCESS/SECRET/TOKEN : +passenv = + # Enables or disables integration tests ('RUN' enables) + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_CONTROL \ + # Identifies AWS KMS key id to use in integration tests + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID \ + # Pass through AWS credentials + AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN sitepackages = False deps = mock @@ -104,7 +113,7 @@ basepython = python3 deps = sphinx doc8 -commands = doc8 doc/index.rst README.rst CHANGELOG.rst CONTRIBUTING.rst +commands = doc8 doc/index.rst README.rst CHANGELOG.rst [testenv:readme] basepython = python3