Skip to main content

Simple, secure, account and credential management

Project description

ACCT

Simple and secure account management

USAGE

Yaml files containing confidential information can be encrypted for use inside of acct base applications. This is an example of what an acct credentials file might look like.

credentials.yml

provider:
  profile_name:
    username: XXXXXXXXXXXX
    password: XXXXXXXXXXXX
    api_key: XXXXXXXXXXXXXXXXXXX

Next use the acct command to encrypt this file using the fernet algorithm:

$ acct encrypt credentials.yml
YeckEnWEGOjBDVxxytw13AsdLgquzhCtFHOs7kDsna8=

The acct command can also be used to decrypt the encrypted file:

$ acct decrypt credentials.yml.fernet --output=yaml --acct-key="YeckEnWEGOjBDVxxytw13AsdLgquzhCtFHOs7kDsna8="

INTEGRATION

CLI

Your own app can extend acct’s command line interface to use the –acct-file and –acct-key options:

my_project/conf.py

CLI_CONFIG = {
    "acct_file": {"source": "acct", "os": "ACCT_FILE"},
    "acct_key": {"source": "acct", "os": "ACCT_KEY"},
    "crypto_plugin": {"source": "acct"},
}

In your own project, you can vertically merge acct and extend it with your own plugins:

my_project/conf.py

DYNE = {
    "acct": ["acct"],
}

PLUGINS

Create the directory my_project/acct/my_project and add your acct plugins there. acct plugins need to implement a gather function. If your app used “hub.acct.init.unlock()” to initialize profile data then you can read profiles from hub.acct.PROFILES as a starting point for sub_profile data. gather() should return a dictionary of processed profiles. Gather functions can be asynchronous or synchronous.

my_project/acct/my_project/my_plugin.py

async def gather(hub):
    """
    Get [my_plugin] profiles from an encrypted file

    Example:

    .. code-block:: yaml

        my_plugin:
          profile_name:
            username: XXXXXXXXXXXX
            password: XXXXXXXXXXXX
            api_key: XXXXXXXXXXXXXXXXXXXXXXX
    """
    processed_profiles = {}
    for profile, ctx in hub.acct.PROFILES.get("my_plugin", {}).items():
        # Create a connection through [some_library] for each of the profiles
        sub_profiles[profile] = {
            "connected": False,
            "connection": await some_library.connect(**ctx),
        }
    return processed_profiles

The gather function can optionally take a “profiles” parameter. “profiles” will be an implicitly passed dictionary of data that was read from the encrypted acct file. This is useful when profiles are collected explicitly by your own program and aren’t stored in the traditional location within acct.

my_project/acct/my_project/my_plugin.py

async def gather(hub, profiles):
    """
    Get [my_plugin] profiles from an encrypted file

    Example:

    .. code-block:: yaml

        my_plugin:
          profile_name:
            username: XXXXXXXXXXXX
            password: XXXXXXXXXXXX
            api_key: XXXXXXXXXXXXXXXXXXXXXXX
    """
    processed_profiles = {}
    for profile, ctx in profiles.get("my_plugin", {}).items():
        # Create a connection through [some_library] for each of the profiles
        sub_profiles[profile] = {
            "connected": False,
            "connection": await some_library.connect(**ctx),
        }
    return processed_profiles

BACKENDS

You can make an acct backend plugin to collect profiles from an alternate source. Backends are processed after the initial encrypted acct_file reading, but before profiles are processed. This makes it so you can define credentials to access an external secret store in your acct_file – and then define extra profiles within that external secret store. acct backend plugins transform data from that external secret store into acct profiles. unlock functions optionally take a profiles parameter and can be synchronous or asynchronous.

my_project/acct/my_project/my_plugin.py

async def unlock(hub):
    """
    Get profiles from an external store

    Example:

    .. code-block:: yaml

        backend_key: my_backend_key

        my_backend_key:
          my_plugin:
            profile_name:
              username: XXXXXXXXXXXX
              password: XXXXXXXXXXXX
              api_key: XXXXXXXXXXXXXXXXXXXXXXX
    """
    backends = hub.acct.PROFILES.get(hub.acct.BACKEND_KEY, {})
    profiles = {}
    for profile, ctx in backends.get("my_plugin", {}).items():
        # Create a connection through [some_library] for each of the profiles
        connection = await some_library.connect(**ctx)

        # get profile information from the connection and turn it into a dictionary that looks like:
        # {"provider": "profile1":  {"kwarg1": "value1"}
        profiles.update(connection.get_profiles())

    return profiles

INTERNAL

Add acct startup code to your project’s initializer:

my_project/my_project/init.py

def __init__(hub):
    # Horizontally merge the acct dynamic namespace into your project
    hub.pop.sub.add(dyne_name="acct")

def cli(hub):
    # Load the config from evbus onto hub.OPT
    hub.pop.config.load(["my_project", "acct"], cli="my_project")

    # decrypt the encrypted file using the given key and populate hub.acct.PROFILES with the decrypted structures
    hub.acct.init.unlock(hub.OPT.acct.acct_file, hub.OPT.acct.acct_key)

    # Process profiles from subs in `hub.acct.my_project` and put them into `hub.acct.SUB_PROFILES`
    # return the explicitly named profile
    profile = hub.acct.init.gather(subs=["my_project"], profile=hub.OPT.acct.acct_profile)

Alternatively, your app can collect profiles explicitly without storing them on the hub:

my_project/my_project/init.py

def __init__(hub):
    # Horizontally merge the acct dynamic namespace into your project
    hub.pop.sub.add(dyne_name="acct")

def cli(hub):
    # Load the config from evbus onto hub.OPT
    hub.pop.config.load(["my_project", "acct"], cli="my_project")

    # Collect profiles without storing them on the hub
    profiles = await hub.acct.init.profiles(hub.OPT.acct.acct_file, hub.OPT.acct.acct_key)

    # Collect subs without storing them on the hub
    sub_profiles = await hub.acct.init.process(["my_project"], profiles)

    # Retrieve a specifically named profile
    profile = await.hub.acct.init.single(
        profile_name=hub.OPT.acct.acct_profile,
        subs=["my_project"],
        sub_profiles=sub_profiles,
        profiles=profiles
    )

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

acct-5.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

acct-5-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

Details for the file acct-5.tar.gz.

File metadata

  • Download URL: acct-5.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.6.1 requests/2.25.1 setuptools/51.1.2 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.1

File hashes

Hashes for acct-5.tar.gz
Algorithm Hash digest
SHA256 6076dcf23b6476e5fe7f32892362d2a12a6c84d1de0f0807b87627308b4b86a0
MD5 f5f6cd20b6b17ba65fb1597c68a5afd3
BLAKE2b-256 edb7a64687fc323a2e59dba09405c80597790979269efbb6a8580a200663d9fa

See more details on using hashes here.

File details

Details for the file acct-5-py3-none-any.whl.

File metadata

  • Download URL: acct-5-py3-none-any.whl
  • Upload date:
  • Size: 12.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.6.1 requests/2.25.1 setuptools/51.1.2 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.1

File hashes

Hashes for acct-5-py3-none-any.whl
Algorithm Hash digest
SHA256 84a7cee419a380367331b6ac0ccddad7da643d06acb84ebeeba8b834ebdcecea
MD5 788feed03c0bbb487703ca48eacbca51
BLAKE2b-256 1d100e7d6bba01000ae81f1523b02a03ebdd050dbaf85a73a870d92ece2973c2

See more details on using hashes here.

Supported by

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