From 0f26134a1d16fd5801443ba819d84e424f9ac3b3 Mon Sep 17 00:00:00 2001 From: Nathan Muir Date: Mon, 3 Oct 2016 15:11:29 +1000 Subject: [PATCH] Use entry points to allow additional cli commands to be loaded. --- README.md | 47 +++++++++++++++++++++------------------ credsmash/cli.py | 29 +++++------------------- credsmash/cli_dynamodb.py | 22 ++++++++++++++++++ credsmash/templates.py | 12 ++++------ setup.py | 4 ++++ 5 files changed, 61 insertions(+), 53 deletions(-) create mode 100644 credsmash/cli_dynamodb.py diff --git a/README.md b/README.md index 35249fc..0218a5e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ some utilities I find useful, see `HISTORY.md` for details. 2. Set up a key called `credsmash` in KMS 3. Make sure you have AWS creds in a place that boto/botocore can read them (eg, [Use environment `AWS_CONFIG_FILE`](http://boto3.readthedocs.io/en/latest/guide/configuration.html#environment-variables)) -4. `credsmash setup` +4. `credsmash setup-dynamodb` ## What is this? @@ -96,7 +96,7 @@ credsmash uses the following AWS services: 1. Set up a key called `credsmash` in KMS 2. `pip install credsmash` 3. Make sure you have AWS creds in a place that boto/botocore can read them -4. Run `credsmash setup` +4. Run `credsmash setup-dynamodb` ### Setting up KMS `credsmash` will not currently set up your KMS master key. To create a KMS master key, @@ -122,7 +122,7 @@ You will need to have AWS credentials accessible to boto/botocore. The easiest t You can specify the region in which `credsmash` should operate by using the `-r` flag, or by setting the `AWS_DEFAULT_REGION` environment variable. Note that the command line flag takes precedence over the environment variable. If you set neither, then `credsmash` will operate against us-east-1. -Once credentials are in place, run `credsmash setup`. This will create the DDB table needed for credential storage. +Once credentials are in place, run `credsmash setup-dynamodb`. This will create the DDB table needed for credential storage. ### Working with multiple AWS accounts (profiles) @@ -148,27 +148,30 @@ See https://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standar Usage: credsmash [OPTIONS] COMMAND [ARGS]... Options: - -c, --config FILENAME - -t, --table-name TEXT DynamoDB table to use for credential storage - -k, --key-id TEXT the KMS key-id of the master key to use. See the - README for more information. Defaults to - alias/credsmash - -p, --profile-name TEXT Boto config profile to use when connecting to AWS - --help Show this message and exit. + -c, --config PATH + -t, --table-name TEXT DynamoDB table to use for credential storage + -k, --key-id TEXT the KMS key-id of the master key to use. See the + README for more information. Defaults to + alias/credsmash + --context ... the KMS encryption context to use.Only works if + --key-id is passed. + --help Show this message and exit. Commands: - delete Delete every version of a single secret - delete-many Delete every version of all matching secrets - find-many Find all secrets matching - find-one Find exactly one secret matching - get Fetch the latest, or a specific version of a... - get-all Fetch the latest version of all secrets - list List all secrets & their versions. - prune Delete all but the latest version of a single... - prune-many Delete all but the latest version of all... - put Store a secret - put-many Store many secrets - setup Setup the credential table in AWS DynamoDB + delete Delete every version of a single secret + delete-many Delete every version of all matching secrets + find-many Find all secrets matching + find-one Find exactly one secret matching + get Fetch the latest, or a specific version of a... + get-all Fetch the latest version of all secrets + list List all secrets & their versions. + prune Delete all but the latest version of a single... + prune-many Delete all but the latest version of all... + put Store a secret + put-many Store many secrets + render-template Render a configuration template.... + render-templates Render multiple configuration templates -... + setup-dynamodb Setup the credential table in AWS DynamoDB ``` ## IAM Policies diff --git a/credsmash/cli.py b/credsmash/cli.py index 965cf44..cfd2338 100644 --- a/credsmash/cli.py +++ b/credsmash/cli.py @@ -13,7 +13,6 @@ import credsmash.api from credsmash.crypto import ALGO_AES_CTR -from credsmash.dynamodb_storage_service import DynamoDbStorageService from credsmash.util import set_stream_logger, detect_format, \ parse_config, read_one, read_many, write_one, write_many @@ -395,25 +394,9 @@ def cmd_put_many(ctx, source, fmt, compare=True): logger.debug('Stored {0} secrets'.format(len(secrets))) -@main.command('setup') -@click.option('--read-capacity', type=click.INT, default=1) -@click.option('--write-capacity', type=click.INT, default=1) -@click.pass_context -def cmd_setup(ctx, read_capacity, write_capacity): - """ - Setup the credential table in AWS DynamoDB - """ - #TODO - allow the dynamodb service to register it's own CLI command - storage_service = ctx.obj.storage_service - if not isinstance(storage_service, DynamoDbStorageService): - raise click.ClickException('Cannot setup unknown storage service') - storage_service.setup( - read_capacity, write_capacity - ) - - -try: - from .templates import templates_cli - main.commands.update(templates_cli.commands) -except ImportError: - pass +# Load any extra CLI's +for ep in pkg_resources.iter_entry_points('credsmash.cli'): + try: + ep.load() + except ImportError: + pass diff --git a/credsmash/cli_dynamodb.py b/credsmash/cli_dynamodb.py new file mode 100644 index 0000000..c59b46f --- /dev/null +++ b/credsmash/cli_dynamodb.py @@ -0,0 +1,22 @@ +from __future__ import absolute_import, division, print_function + +import click +from .cli import main +from .dynamodb_storage_service import DynamoDbStorageService + + +@main.command('setup-dynamodb') +@click.option('--read-capacity', type=click.INT, default=1) +@click.option('--write-capacity', type=click.INT, default=1) +@click.pass_context +def cmd_setup(ctx, read_capacity, write_capacity): + """ + Setup the credential table in AWS DynamoDB + """ + storage_service = ctx.obj.storage_service + if not isinstance(storage_service, DynamoDbStorageService): + raise click.ClickException('Cannot setup unknown storage service') + storage_service.setup( + read_capacity, write_capacity + ) + diff --git a/credsmash/templates.py b/credsmash/templates.py index 34d47dc..52414f0 100644 --- a/credsmash/templates.py +++ b/credsmash/templates.py @@ -11,7 +11,8 @@ import jinja2.sandbox import credsmash.api -from credsmash.util import read_many, shell_quote, parse_manifest, detect_format +from .util import read_many, shell_quote, parse_manifest, detect_format +from .cli import main logger = logging.getLogger(__name__) @@ -35,12 +36,7 @@ def __getitem__(self, key): return self._data[key] -@click.group() -def templates_cli(): - pass - - -@templates_cli.command('render-template') +@main.command('render-template') @click.argument('template', type=click.File(mode='r', encoding='utf-8')) @click.argument('destination', type=click.File(mode='w', encoding='utf-8')) @click.option('--obj-name', default='secrets', @@ -80,7 +76,7 @@ def cmd_render_template( destination.write(output) -@templates_cli.command('render-templates') +@main.command('render-templates') @click.argument('manifest', type=click.File(mode='r', encoding='utf-8')) @click.option('--manifest-format', default=None) @click.option('--obj-name', default='secrets', diff --git a/setup.py b/setup.py index fefdebb..3b42e5d 100644 --- a/setup.py +++ b/setup.py @@ -78,6 +78,10 @@ def read_markdown(*file_paths): 'credsmash.storage_service': [ 'dynamodb = credsmash.dynamodb_storage_service:DynamoDbStorageService', ], + 'credsmash.cli': [ + 'templates = credsmash.templates', + 'dynamodb = credsmash.cli_dynamodb' + ] }, classifiers=[