Skip to main content

Abstractions to read / write / delete secrets from keyrings, vaults, flat files, etc

Project description

cred_manage is for managing credentials.

The cred_manage package contains classes for managing credentials or secrets.

The Abstract Base Class CredContainerBase is defined in base_cred_container.py.

Subclasses of CredContainerBase are called "Credential Containers"

There are 3 methods which are intended to be overridden by subclasses. If not implemented, a NotImplementedError will be raised. Sometimes this might be perfectly appropriate, and you should catch these exceptions as applicable.

These are:

  • get_cred() - Used to get a credential out of a credential container.
  • set_cred() - If implemented, used to set a credential within a credential container.
  • delete_cred() - If implemented, used to delete a credential within a credential container.

A Credential container can really be anything that is reasonably responsible to keep credentials, keys, or other secret things inside of. For example:

  • A Password Manager like Bitwarden or Lastpass
  • A Flat File (Containing an API Key, for example) **
  • A Keychain, like that in MacOS

Currently, the cred_manage package has these Credential Containers implemented (Contributions are welcome!):

  • FlatFileCredContainer - Used to interact with flat files containing passwords or other secret things. **Please read the warnings below and take them to heart.
  • BitwardenCredContainer - Used to interact with Bitwarden Password Manager.

A common pattern might be to use a FlatFileCredContainer to manage the context necessary to subsequently log into and interact with a Password Manager tool, like Bitwarden (BitwardenCredContainer) or Lastpass, or a Keychain, which are surely better places to keep sensitive information than flat files.

FlatFileCredContainer

First things first:

Never, never, never, EVER commit passwords or other secrets into version control.

Never. DO NOT DO IT!

Instead:

  • Write your code such that it references and reads sensitive information from outside of the repository (e.g. A config file containing a path to another file outside of version control).
  • Avoid keeping sensitive information in flat files in the first place. If you find yourself with more than just a few secrets in flat files, you should probably rethink your design.
  • For cases where you do decide to keep secrets in flat files, be very sure that the machine on which they reside is sufficiently locked down (beyond the scope of this README.md other than to say: Not exposed to the internet, no superfluous open ports, and login passwords required for all users.)

With that warning behind us...

FlatFileCredContainer isn't complex at all. It doesn't do much more than the standard Python library can do to read from and write to a file with a file handle. One feature that it does implement is that by default, it will be stubborn (this can be overridden) about interacting with files for which the permission bits are too broad, in which case an exception will be raised.

FlatFileCredContainer might be a good place to keep API keys, bearer tokens, or anything else that is needed to bootstrap some process or otherwise allow for automation without human interaction.

BitwardenCredContainer

BitwardenCredContainer is a wrapper around the Bitwarden CLI. It is NOT a wrapper around the Bitwarden API, which as far as this author can tell is only available to Enterprise Organization plans. If you're a user of an Enterprise Organization plan, you'll probably want to interact with he API directly, using the Python requests library, rather than this package.

Thus, a prerequisite is that you'll have installed the Bitwarden CLI ahead of time.

BitwardenCredContainer can be instantiated directly but for convenience, a factory function, make_bitwarden_container() is provided. make_bitwarden_container() accepts just a single argument, which is a path to a flat JSON file with the proper context to instantiate the class via the __init__ method. The contents of the file should look like this:

{
    "client_id": "<YOUR CLIENT ID HERE>",
    "client_secret": "<YOUR CLIENT SECRET HERE>",
    "scope": "api",
    "grant_type": "client_credentials",
    "email_address": "<you@yourdomain.com HERE, OPTIONALLY.>"
}

Note that the email_address key is optional, to suppress a subsequent prompt for your email address.

About Vault Items and GUIDs

BitwardenCredContainer is a container around your entire Bitwarden vault. The vault is initially loaded in it's entirety, but all passwords are redacted and replaced with the string <password removed>, in the spirit of paranoia. Subsequent calls to methods that would return an actual password, make a secondary call to the CLI to retrieve just that password and return the actual value. Such methods are listed below and do what you think they might based on their names (more context in Docstrings, if needed):

  • get_cred()
  • get_vault_item_by_guid()
  • get_credentials_by_guid()
  • get_username_by_guid()
  • get_password_by_guid()

Each of these methods accepts a GUID, which serves as the 'primary key' for the vault item in question. If you need to find the GUID for a given item, you can instantiate a BitwardenCredContainer object and invoke the print_items() method (This will not print passwords). Alternatively, you can directly invoke the Bitwarden CLI using the bw list items command (Consider piping into jq for readability) to find the GUID (under the id key) for any given vault item.

About the BW_SESSION environment variable.

When logging into Bitwarden via the CLI, a Session Key is returned, which can be exported to the environment variable BW_SESSION to suppress subsequent prompts for the master password. When instantiating BitwardenCredContainer, a check is performed to see if the BW_SESSION is set. If it is set (and valid), YOU WILL NOT be prompted for the master password, interactively. If it is not set, YOU WILL be prompted for the master password for each instantiation. Depending on your use case, exploit this functionality (or not) as appropriate. Hint: Consider the ways in which you might be able to temporarily store this value in a FlatFileCredContainer object, only to destroy it when you're done.

Example Usage.

In this example we use a FlatFileCredContainer object to read the necessary context to instantiate a BitwardenCredContainer object out of a flat file. Then, we print the GUIDs and corresponding names of the items from the Bitwarden Vault

from cred_manage.flat_file import FlatFileCredContainer
from cred_manage.bitwarden import BitwardenCredContainer
import json

# Instantiate Flat File Credential Container
ff_obj = FlatFileCredContainer(file_path='/.credentials/bw_api.json', allow_broad_permissions=False)

# Read the JSON contents out of the Flat file Credential Container
j = json.loads(ff_obj.read())

# Use those JSON contents to instantiate a Bitwarden Credential Container
bw = BitwardenCredContainer(**j)  #  <-- If environment variable BW_SESSION is set, then no interactive password prompt here.

# Print the GUIDs and corresponding names of vault items
bw.print_items()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cred_manage-0.0.5.tar.gz (14.9 kB view hashes)

Uploaded Source

Built Distribution

cred_manage-0.0.5-py3-none-any.whl (13.6 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page