Skip to content
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

Add option to load KMS master key ID from the CREDSTASH_KMS_KEY_ID environment variable #292

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# CredStash

## Quick Installation
0. (Linux only) Install dependencies
0. (Linux only) Install dependencies
1. `pip install credstash`
2. Set up a key called credstash in KMS (found in the IAM console)
3. Make sure you have AWS creds in a place that boto/botocore can read them
4. `credstash setup`

### Linux install-time dependencies
Credstash recently moved from PyCrypto to `cryptography`. `cryptography` uses pre-built binary wheels on OSX and Windows, but does not on Linux. That means that you need to install some dependencies if you want to run credstash on linux.
Credstash recently moved from PyCrypto to `cryptography`. `cryptography` uses pre-built binary wheels on OSX and Windows, but does not on Linux. That means that you need to install some dependencies if you want to run credstash on linux.

For Debian and Ubuntu, the following command will ensure that the required dependencies are installed:
```
Expand All @@ -31,7 +31,7 @@ Some organizations build complete credential-management systems, but for most of

CredStash is a very simple, easy to use credential management and distribution system that uses AWS Key Management Service (KMS) for key wrapping and master-key storage, and DynamoDB for credential storage and sharing.

## Compatibility with Other Languages
## Compatibility with Other Languages
A number of great projects exist to provide credstash compatability with other languages. Here are the ones that we know about (feel free to open a pull request if you know of another):

- https://github.com/jessecoyle/jcredstash (Java)
Expand Down Expand Up @@ -88,7 +88,7 @@ credstash uses the following AWS services:
2. Go to the KMS Console
3. Click "Customer managed keys" in the left sidebar
4. Click "Next" to configure a Symmetric key
5. For alias, put "credstash" and click "Next". If you want to use a different name, be sure to pass it to credstash with the `-k` flag.
5. For alias, put "credstash" and click "Next". If you want to use a different name, be sure to pass it to credstash with the `-k` flag or the `CREDSTASH_KMS_KEY_ID` environment variable.
6. Decide what IAM principals, if any, you want to be able to manage the key. Click "Next".
6. On the "Key Usage Permissions" screen, pick the IAM users/roles that will be using credstash (you can change your mind later). Click "Next".
7. Review the key policy and click "Finish".
Expand Down Expand Up @@ -246,8 +246,9 @@ put
optional arguments:
-h, --help show this help message and exit
-k KEY, --key KEY the KMS key-id of the master key to use. See the
README for more information. Defaults to
alias/credstash
README for more information. If not specified
credstash will use the `CREDSTASH_KMS_KEY_ID`
environment variable or default of alias/credstash
-c COMMENT, --comment COMMENT
Include reference information or a comment about value
to be stored.
Expand Down Expand Up @@ -372,7 +373,7 @@ python -m unittest discover -v tests "*.py"

### Running the integration tests using BATS
1. The integration tests require a working install of credstash. I recommend not using your primary development/production install.
2. Download and install BATS: https://github.com/sstephenson/bats
2. Download and install BATS: https://github.com/sstephenson/bats
3. Run the tests: `bats integration_tests/`

New integration test PRs are welcome!
Expand Down
62 changes: 34 additions & 28 deletions credstash.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def setup_logging(level, log_file):
handler = logging.FileHandler(log_file)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(handler)
logger.setLevel(level)


Expand Down Expand Up @@ -352,7 +352,7 @@ def putSecret(name, secret, version="", kms_key="alias/credstash",


def putSecretAutoversion(name, secret, kms_key="alias/credstash",
region=None, kms_region=None,
region=None, kms_region=None,
table="credential-store", context=None,
digest=DEFAULT_DIGEST, comment="", **kwargs):
"""
Expand Down Expand Up @@ -398,13 +398,13 @@ def getAllSecrets(version="", region=None, kms_region=None, table="credential-st
pool = ThreadPool(min(len(names), THREAD_POOL_MAX_SIZE))
results = pool.map(
lambda credential: getSecret(
credential,
version=version,
region=region,
table=table,
context=context,
dynamodb=dynamodb,
kms=kms,
credential,
version=version,
region=region,
table=table,
context=context,
dynamodb=dynamodb,
kms=kms,
**kwargs
), names)
pool.close()
Expand Down Expand Up @@ -457,8 +457,8 @@ def putSecretAction(args, region, kms_region, **session_params):
if(args.prompt):
value = getpass("{}: ".format(args.credential))
if putSecret(args.credential, value, version=version,
kms_key=args.key, region=region, kms_region=kms_region,
table=args.table, context=args.context, digest=args.digest,
kms_key=args.key, region=region, kms_region=kms_region,
table=args.table, context=args.context, digest=args.digest,
comment=args.comment, **session_params):
print("{0} has been stored".format(args.credential))
except KmsError as e:
Expand Down Expand Up @@ -530,9 +530,9 @@ def getSecretAction(args, region, kms_region, **session_params):
sys.stdout.write(output_func(secrets, **output_args))
else:
sys.stdout.write(getSecret(
args.credential,
args.credential,
version=args.version,
region=region,
region=region,
kms_region=kms_region,
table=args.table,
context=args.context,
Expand Down Expand Up @@ -634,7 +634,7 @@ def getKmsRegion():

def loadConfig():
config = os.path.expanduser("~/.credstash")

try:
with open(config) as f:
options = json.load(f)
Expand Down Expand Up @@ -894,7 +894,7 @@ def get_parser():
"or if that is not set, the value in "
"`~/.aws/config`. As a last resort, "
"it will use " + DEFAULT_REGION)
parsers['super'].add_argument("--kms-region", type=str, default=None,
parsers['super'].add_argument("--kms-region", type=str, default=None,
help="Region the credstash KMS key will be read from, "
"independent of the region the DDB table is in. If not specified, "
"the KMS region will follow the same resolution path as --region. "
Expand All @@ -907,7 +907,7 @@ def get_parser():
"CREDSTASH_DEFAULT_TABLE env variable, "
"or if that is not set, the value "
"`credential-store` will be used")
parsers['super'].add_argument("--log-level",
parsers['super'].add_argument("--log-level",
help="Set the log level, default WARNING",
default='WARNING'
)
Expand All @@ -916,7 +916,7 @@ def get_parser():
"printed to stderr and stack traces are logged to file",
default='credstash.log'
)

role_parse = parsers['super'].add_mutually_exclusive_group()
role_parse.add_argument("-p", "--profile", default=None,
help="Boto config profile to use when "
Expand Down Expand Up @@ -1010,10 +1010,13 @@ def get_parser():
help="encryption context key/value pairs "
"associated with the credential in the form "
"of \"key=value\"")
parsers[action].add_argument("-k", "--key", default="alias/credstash",
help="the KMS key-id of the master key "
"to use. See the README for more "
"information. Defaults to alias/credstash")
parsers[action].add_argument("-k", "--key",
default=os.environ.get("CREDSTASH_KMS_KEY_ID", "alias/credstash"),
help="the KMS key-id of the master key to use. "
"See the README for more information. If not "
"specified credstash will use the "
"CREDSTASH_KMS_KEY_ID environment variable or "
"default of alias/credstash")
parsers[action].add_argument("-c", "--comment", type=str,
help="Include reference information or a comment about "
"value to be stored.")
Expand Down Expand Up @@ -1050,10 +1053,13 @@ def get_parser():
help="encryption context key/value pairs "
"associated with the credential in the form "
"of \"key=value\"")
parsers[action].add_argument("-k", "--key", default="alias/credstash",
help="the KMS key-id of the master key "
"to use. See the README for more "
"information. Defaults to alias/credstash")
parsers[action].add_argument("-k", "--key",
default=os.environ.get("CREDSTASH_KMS_KEY_ID", "alias/credstash"),
help="the KMS key-id of the master key to use. "
"See the README for more information. If not "
"specified credstash will use the "
"CREDSTASH_KMS_KEY_ID environment variable or "
"default of alias/credstash")
parsers[action].add_argument("-v", "--version", default="",
help="Put a specific version of the "
"credential (update the credential; "
Expand All @@ -1075,10 +1081,10 @@ def get_parser():
action = 'setup'
parsers[action] = subparsers.add_parser(action,
help='setup the credential store')
parsers[action].add_argument("--save-kms-region", type=str, default=None,
parsers[action].add_argument("--save-kms-region", type=str, default=None,
help="Save the region the credstash KMS key will be read from, "
"independent of the region the DDB table is in. This value is saved "
"in ~/.credstash")
"in ~/.credstash")
parsers[action].add_argument("--tags", type=key_value_pair,
help="Tags to apply to the Dynamodb Table "
"passed in as a space sparated list of Key=Value", nargs="*")
Expand Down Expand Up @@ -1108,7 +1114,7 @@ def main():

# get KMS region (otherwise it is the same as region)
kms_region = args.kms_region or getKmsRegion() or region

if "action" in vars(args):
if args.action == "delete":
deleteSecrets(args.credential,
Expand Down