GithubHelp home page GithubHelp logo

discreetly's Introduction

PyPI version fury.io PyPI pyversions

discreetly

A secrets manager for AWS and GCP

$ discreetly set acme/github/api-token my-secret-api-key
$ discreetly get acme/github/api-token
my-secret-api-key
$ discreetly --profile prod list acme/
['acme/prod/postgres/passwd', 'acme/prod/github/api-token']

Applications often require access to secrets such as database passwords or API keys. A really bad way to manage those secrets would be to bake them into your code and then check them into source control. Marginally better would be storing secrets in environment variables. If your applications are running on AWS or GCP, both platforms provide tooling for better secrets management.

discreetly provides a consistent API for managing secrets across both AWS and GCP. It encourages you to partition your secrets and encryption keys so that your web application only has access to the secrets it needs to run and not, for example, access to infrastructure secrets only needed by your infrastructure management tools.

Installation

discreetly does not set up any infrastructure for you. At a minimum, you need to have i) credentials available for authenticating with AWS and/or Google, ii) permissions to use KMS to encrypt and decrypt secrets, and iii) permissions to read/write to the underlying store.

To install the discreetly cli with support for AWS and GCP:

$ pip install discreetly[cli]

For use as a library, install discreetly specifying which backends you need to support, e.g.:

$ pip install discreetly[aws,gcp]

Configuration

discreetly can be configured with a JSON file, e.g.:

{
  "acme": {
    "type": "aws"
  },
  "default": {
    "type": "gcp",
    "datastore_project": "acme-corp",
    "keyid": "projects/acme-corp-kms/locations/global/keyRings/discreetly/cryptoKeys/default"
  }
}

In the above example, the configuration contains two profiles, "acme" and "default". A profile must specify a type, either "aws" or "gcp".

Because a profile can specify a keyid, you can have named profiles not only for different cloud providers but for different KMS keys, e.g. one for dev, another for prod.

discreetly will search for a configuration file at the location provided by the environment variable DISCREETLY_CONFIG_FILE, falling back to a file named discreetly.json in the current directory.

Frequently Asked Questions (FAQ)

  1. What about credstash/Chamber/Vault/etc.?

    discreetly was actually inspired by credstash. However, credstash only supports AWS and it pre-dates Parameter Store. That said, there are use cases where a DynamoDB backend might be preferred (e.g. parameters greater than 4096 characters).

    Chamber is excellent choice, especially in a Go environment or if you only need AWS support.

    Vault is great if you have the resources to support it.

Troubleshooting

Most issues are related to authentication or permissions with your cloud provider.

With the discreetly cli, you can also change the logging level by setting the LOGLEVEL environment variable, e.g.

$ LOGLEVEL=DEBUG discreetly get my/super/secret

AWS

If you have the AWS CLI installed, verify that you can use it to access Parameter Store, e.g.:

$ aws ssm get-parameter /path/to/parameter --with-decryption

If that works, then the problem may very well be with discreetly and you should consider opening an issue.

However, if that's not working, it's likely a configuration or authentication issue. Under the hood, discreetly uses Boto 3, so consult their documentation on setting up your authentication credentials.

GCP

Unfortunately, gcloud doesn't support much of the Datastore API, so it's a little harder to sanity test any issues in your local environment.

Verify that you've followed the steps in Obtaining and providing service account credentials manually, in particular:

  1. Creating a service account
  2. Saving the JSON file for the service account locally
  3. Setting the path to the JSON file in the environment variable, GOOGLE_APPLICATION_CREDENTIALS

Library usage

$ pip install discreetly[aws,gcp]
import discreetly

cfg = {
    "default": {
        "type": "gcp",
        "datastore_project": "acme-corp",
        "keyid": "projects/acme-corp-kms/locations/global/keyRings/discreetly/cryptoKeys/default"
    },
    "acme-aws": {
        "type": "aws",
        "keyid: "alias/discreetly_key",
    }
}

d = discreetly.Session.create(cfg) # uses the 'default' profile
d.set('my-service/my-key', 'my_value')
d.get('my-service/my_key')

acme = discreetly.session.create(config=cfg, profile='acme-aws') # uses the 'acme-aws' profile
acme.set('acme/dev/postgres/password', 'open-sesame')
acme.get('acme/dev/postgres/password')

acme.set('acme/prod/postgres/password', 'super-secret', keyid='alias/prod_key')
acme.get('acme/prod/postgres/password') # no need to specify the keyid for get

Development

discreetly is written in Python and supports Python 2.7 and 3.6+

After cloning the repo, run pip install -r requirements.txt to install the required development dependencies (e.g. pytest, flake8, etc.)

You can run pytest to run the unit tests locally or tox to run all the tests under Python 2.7 and 3.x.

Note from version 0.2.0 onwards, discreetly only supports Python 3.6+

Releases

  • Review and update CHANGELOG.md in a new release branch

    • The following will show commits since the last tag beginning with 'v':

      $ git log $(git describe --tags --match "v*" --abbrev=0)..HEAD`
    • Replace [Unreleased] with the new semver and release date, e.g. [0.1.2] - 2019-12-13

    • Add a new [Unreleased] placeholder above the new version you just created

  • Create a new PR

    • The following lists all commits since the last tag, which may be useful for including in the PR description:

      git log --pretty=format:"* %h %s" $(git describe --tags --abbrev=0 @^)..@

  • Once the PR is merged to master and passes all status checks, create and push a new signed, annotated tag, e.g.:

    $ LAST_VERSION=$(git describe --tags --match "v*" --abbrev=0)
    $ VERSION=v0.1.1
    $ awk "/^## \[${VERSION}/{flag=1;}/## \[${LAST_VERSION}/{flag=0} flag" CHANGELOG.md | git tag -s -a ${VERSION} --cleanup=whitespace -F -
    $ git push --follow-tags

    The awk command above grabs the contents of the CHANGELOG for $VERSION to include as the message for the annotated git tag. It's fairly brittle in its assumptions about the format of the CHANGELOG. so you might just run the awk command:

    awk "/^## \[${VERSION}/{flag=1;}/## \[${LAST_VERSION}/{flag=0} flag" CHANGELOG.md

    as a sanity check before creating & pushing the tag.

discreetly's People

Contributors

eddies avatar ghosalya avatar minhducvt293 avatar

Stargazers

Everton Yoshitani avatar

Watchers

 avatar James Cloos avatar  avatar  avatar

Forkers

minhducvt293

discreetly's Issues

[stub] GCS backend

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Configurable log level for cli

Is your feature request related to a problem? Please describe.
The cli loglevel is currently hardcoded to DEBUG, which is very spammy.

Describe the solution you'd like
A saner default loglevel (probably WARN).
Some way to configure the loglevel on the fly, e.g. discreetly --loglevel INFO ...

Support XDG_CONFIG_HOME for configuration file

Is your feature request related to a problem? Please describe.
Currently, discreetly looks for a config file at a location defined by the environment variable DISCREETLY_CONFIG_FILE falling back to a file named discreetly.json in the current directory. discreetly should also look in XDG_CONFIG_HOME.

Describe the solution you'd like

Look for/use in the following order:

  1. DISCREETLY_CONFIG_FILE
  2. XDG_CONFIG_HOME/discreetly/discreetly.json if XDG_CONFIG_HOME is defined, else ~/.config/discreetly/discreetly.json
  3. discreetly.json in current directory

Additional context

  • appdirs
    I don't know that we want to actually use this library. And for macOS, it would use ~/Library/Preferences/discreetly/discreetly.json, which I'm not a fan of for discreetly (although there is an old, open issue requesting XDG_CONFIG_HOME for macOS).
    That said, not sure how we should handle Windows users. appdirs would use the following depending on which Windows and whether or not roaming is set:

    • Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\discreetly\discreetly.json
    • Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\discreetly\discreetly.json
    • Win 7 (not roaming): C:\Users\<username>\AppData\Local\discreetly\discreetly.json
    • Win 7 (roaming): C:\Users\<username>\AppData\Roaming\discreetly\discreetly.json

LGPL 2.1 license incompatibility with Apache

Is your feature request related to a problem? Please describe.
discreetly has a handful of direct, runtime dependencies:

Library License
click BSD 3-Clause
boto3 Apache 2.0
google-cloud-kms Apache 2.0
google-cloud-datastore Apache 2.0

as well as a number of development-only dependencies

Library License
tox MIT
pytest MIT
moto Apache 2.0

Evidently, the LGPL 2.1 license that was chosen for discreetly is incompatible with (at least) the Apache 2.0 license:

this license is not compatible with GPL version 2, because it has some requirements that are not in that GPL version. These include certain patent termination and indemnification provisions.

However, the GPL version 3 (and thereby the LGPLv3) is compatible with Apache 2.0 (at least in one direction). Per the ASF:

Apache 2 software can therefore be included in GPLv3 projects, because the GPLv3 license accepts our software into GPLv3 works. However, GPLv3 software cannot be included in Apache projects. The licenses are incompatible in one direction only, and it is a result of ASF's licensing philosophy and the GPLv3 authors' interpretation of copyright law.

This licensing incompatibility applies only when some Apache project software becomes a derivative work of some GPLv3 software, because then the Apache software would have to be distributed under GPLv3. This would be incompatible with ASF's requirement that all Apache software must be distributed under the Apache License 2.0.

There's an old, long discussion about the ASF's policy decision to disallow LGPL'ed (v2 or 3) software in their own projects--emphasis on policy rather than legal decision.

Describe the solution you'd like
At the least, discreetly should be relicensed under LGPLv3.
Possibly, consider relicensing under another license entirely, e.g. Apache 2.0

Additional context

[stub] S3 backend

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.