Package: secretbox
secretboxA library that offers a simple method of loading and accessing environmental
variables,.envfile values, and other sources of secrets. The class stores
values to state when load methods are called.Loaded values are also injected into the local environ. This is to assist with
adjacent libraries that referenceos.environvalues by default. Required
values can be kept in a.envfile instead of managing a script to load them
into the environment.Note: The default behavior ofsecretboxis to hide exceptions during
loading. This places the detection of missing values on the caller. This
behavior can be altered by passingcapture_exceptions=Falseto any loader.
Exceptions will be raised from their source asLoaderException.RequirementsPython >=3.7Optional Dependenciesboto3boto3-stubs[secretsmanager]boto3-stubs[ssm]Installation$pipinstallsecretboxOptional AWS support$pipinstallsecretbox[aws]The optional aws package includes boto3. If you are using secretbox on AWS
objects that already have boto3 install, such as lambda, this remains an
optional package for your deploy.Documentation:Example use withauto_load=TrueThis loads the system environ and the.envfrom the current working directory
into the class state for quick reference. Loaded secrets can be accessed from
the.get()method or from other methods such asos.getenviron().fromsecretboximportSecretBoxsecrets=SecretBox(auto_load=True)defmain()->int:"""Main function"""my_sevice_password=secrets.get("SERVICE_PW")# More codereturn0if__name__=="__main__":raiseSystemExit(main())Example use withuse_loaders()Loaders collect key:value pair secrets from various sources. When you need more
than one source loaded, in a particular order, with a single collection of all
loaded values then.use_loaders()is the solution. Each loader is executed in
turn and the results compiled with theSecretBoxobject.This loads the system environment variables, an AWS secret store, and then a
specific.envfile if it exists. Secrets are loaded in the order of loaders,
replacing any matching keys from the prior loader.fromsecretboximportSecretBoxsecrets=SecretBox()defmain()->int:"""Main function"""secrets.use_loaders(secrets.EnvironLoader(),secrets.AWSSecretLoader("mySecrets","us-east-1"),secrets.EnvFileLoader("sandbox/.override_env"),)my_sevice_password=secrets.get("SERVICE_PW")# More codereturn0if__name__=="__main__":raiseSystemExit(main())Example use with stand-alone loaderLoaders can be used as needed. For this example we only need to load an AWS
Parameter store.fromsecretboximportAWSParameterStoreLoadersecrets=AWSParameterStoreLoader("mystore/params/","us-west-2")secrets.run()defmain()->int:"""Main function"""my_sevice_password=secrets.get("SERVICE_PW")# More codereturn0if__name__=="__main__":raiseSystemExit(main())SecretBox arguments:SecretBox(*, auto_load: bool = False, load_debug: bool = False)auto_loadLoads environment variables and then the .env file from current working
directory if found.load_debugWhen true, internal logger level is set to DEBUG. Secret values are truncated,
however it is not recommended to leave this on for production deployments.note:Does not enable debug output for aws loaders.SecretBox API:.valuesProperty: A copy of thedict[str, str]key:value pairs loaded.use_loaders(*loaders: Loader) -> NoneLoaded results are injected into environ and stored in state.NOTE:All .get methods pull from the instance state of the class and do not
reflect changes to the enviornment post-load..get(key: str, default: str | None = None) -> strReturns the string value of the loaded value by key name. If the key does not
exists thenKeyErrorwill be raised unless a default is given, then that is
returned..set(key: str, value: str) -> NoneAdds the key:value pair to both the secretbox instance and the environment
variablesLoadersAll loaders follow the same abstract base class. Calling.run()will load
secrets from the loader's source. Each loader will have optional parameters
definable on instantiation.EnvironLoaderLoad system environ valuesEnvFileLoaderLoad local .env file.Args:filename: [str] Optional filename (with path) to load, default is.envAWSSecretLoaderLoad secrets from an AWS secret manager.Args:aws_sstore: [str] Name of the secret store (not the arn)Can be provided through environAWS_SSTORE_NAMEaws_region: [str] Regional location of secret storeCan be provided through environAWS_REGION_NAMEorAWS_REGIONKeyword Args:hide_boto_debug: [bool, default =True]Hides debug logging output from botocore clients to prevent exposing
plain-text secretscapture_exceptions: [bool, default =True]All internal exceptions are captured, logged, and ignored.Raises:LoaderExceptionifcapture_exceptionsisFalse. All exceptions are
raised from their source.AWSParameterStoreLoaderLoad secrets from AWS parameter store.Args:aws_sstore: [str] Name of parameter or path of parameters if endings with/Can be provided through environAWS_SSTORE_NAMEaws_region: [str] Regional Location of parameter(s)Can be provided through environAWS_REGION_NAMEorAWS_REGIONKeyword Args:hide_boto_debug: [bool, default =True]Hides debug logging output from botocore clients to prevent exposing
plain-text secretscapture_exceptions: [bool, default =True]All internal exceptions are captured, logged, and ignored.Raises:LoaderExceptionifcapture_exceptionsisFalse. All exceptions are
raised from their source.A note about logging outputThis library restricts anyDEBUGlogging output during the use of aboto3client or the methods of that client. This is to prevent the logging of your
secrets as well as the bearer tokens used within AWS. You can disable this at
the aws loader by adjustinghide_boto_debugto beFalse. You will need to
define your own instance of theAWSParameterStoreorAWSSecretLoaderand
adjust their flag before callingload_values()..envfile formatCurrent format for the.envfile supports strings only and is parsed in the
following order:Each seperate line is considered a new possible key/value setEach set is delimted by the first=foundLeadingexportkeyword is removed from key, case agnosticLeading and trailing whitespace are removedMatched leading/trailing single quotes or double quotes will be stripped from
values (not keys).I'm open to suggestions on standards to follow here. This is compiled from
"crowd standard" and what is useful at the time.This.envexample:# Comments are ignored

KEY=value

Invalid lines without the equal sign delimiter will also be ignoredWill be parsed as:{"KEY":"value"}This.envexample:export PASSWORD = correct horse battery staple
USER_NAME="not_admin"

MESSAGE = '    Totally not an "admin" account logging in'Will be parsed as:{"PASSWORD":"correct horse battery staple","USER_NAME":"not_admin","MESSAGE":'    Totally not an "admin" account logging in',}Local developer installationIt isstronglyrecommended to use a virtual environment
(venv) when working with python
projects. Leveraging avenvwill ensure the installed dependency files will
not impact other python projects or any system dependencies.The following steps outline how to install this repo for local development. See
theCONTRIBUTING.mdfile in the repo root for information
on contributing to the repo.Windows users: Depending on your python install you will usepyin place
ofpythonto create thevenv.Linux/Mac users: Replacepython, if needed, with the appropriate call to
the desired version while creating thevenv. (e.g.python3orpython3.8)All users: Once inside an activevenvall systems should allow the use ofpythonfor command line instructions. This will ensure you are using thevenv's python and not the system level python.Installation stepsClone this repo and enter root directory of repo:gitclonehttps://github.com/Preocts/secretboxcdsecretboxCreate thevenv:python-mvenvvenvActivate thevenv:# Linux/Mac.venv/bin/activate# Windowsvenv\Scripts\activateThe command prompt should now have a(venv)prefix on it.pythonwill now
call the version of the interpreter used to create thevenvInstall editable library and development requirements:#Updatepipandtools$python-mpipinstall--upgradepip#Installeditableversionoflibrary$python-mpipinstall--editable.[dev]Install pre-commit(see below for details):$pre-commitinstallMisc StepsRun pre-commit on all files:$pre-commitrun--all-filesRun tests:$toxBuild dist:$python-mpipinstall--upgradebuild$python-mbuildTo deactivate (exit) thevenv:$deactivateNote on flake8:flake8is included in therequirements-dev.txtof the project. However it
disagrees withblack, the formatter of choice, on max-line-length and two
general linting errors..pre-commit-config.yamlis already configured to
ignore these.flake8doesn't supportpyproject.tomlso be sure to add the
following to the editor of choice as needed.--ignore=W503,E203--max-line-length=88pre-commitA framework for managing and maintaining multi-language pre-commit hooks.This repo is setup with a.pre-commit-config.yamlwith the expectation that
any code submitted for review already passes all selected pre-commit checks.pre-commitis installed with the development requirements and runs seemlessly
withgithooks.MakefileThis repo has a Makefile with some quality of life scripts if the system
supportsmake.  Please note there are no checks for an activevenvin the
Makefile.PHONYDescriptioninstall-devinstall development/test requirements and project as editable installcoverageRun tests with coverage, generate console report`docker-test'Run coverage and tests in a docker container.build-distBuild source distribution and wheel distributioncleanDeletes build, tox, coverage, pytest, mypy, cache, and pyc artifacts