Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fictive-kin/dynaconf-aws-loader
A Dynaconf loader for AWS Systems Manager Parameter Store that can query slash-delimited hierarchical configuration data.
https://github.com/fictive-kin/dynaconf-aws-loader
Last synced: 12 days ago
JSON representation
A Dynaconf loader for AWS Systems Manager Parameter Store that can query slash-delimited hierarchical configuration data.
- Host: GitHub
- URL: https://github.com/fictive-kin/dynaconf-aws-loader
- Owner: fictive-kin
- License: mit
- Created: 2023-06-02T03:09:22.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2023-07-21T00:35:06.000Z (over 1 year ago)
- Last Synced: 2024-10-05T23:53:12.324Z (about 1 month ago)
- Language: Python
- Size: 53.7 KB
- Stars: 5
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.rst
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
Dynaconf AWS Systems Manager Parameter Store Loader
====================================================When configured, this loader will permit Dynaconf to query `AWS Systems Manager Parameter Store `_ for slash-delimited hierarchical configuration data.
Loader Configuration
--------------------An example:
.. code-block:: python
from dynaconf import Dynaconf
settings = Dynaconf(
environments=True,
settings_file="settings.toml",
LOADERS_FOR_DYNACONF=[
"dynaconf_aws_loader.loader",
"dynaconf.loaders.env_loader"
],
)Note that for the basic functioning of this loader, the `environments `_ option for ``Dynaconf`` must be set, and an environment must be used.
Configuration Variables
-----------------------Both of the following configuration values should be set in the *environment* to avoid a chicken/egg scenario for initializing this custom loader:
- ``SSM_PARAMETER_PROJECT_PREFIX_FOR_DYNACONF``: Required.
The ``project`` prefix in the parameter store path. For example, if the parameter hierarchy looks something like ``/baldur/development/database_uri``, then in this case ``SSM_PARAMETER_PROJECT_PREFIX_FOR_DYNACONF=baldur``.- ``SSM_PARAMETER_NAMESPACE_FOR_DYNACONF``: Optional.
This provides an additional level of grouping once the project and environment have been determined. For example, if the parameter hierarchy looks something like ``/baldur/pr-123/development/database_uri``, then ``SSM_PARAMETER_NAMESPACE_FOR_DYNACONF=pr-123``... note::
If a namespace is utilized, be aware that namespaced settings will be *merged* with non-namespaced settings. This merge is a naive one, where namespaced settings will completely overwrite non-namespaced settings with the same key.The following optional variables should be set in your ``settings.toml`` (or equivalent format), if desired:
- ``SSM_ENDPOINT_URL_FOR_DYNACONF``: If your AWS SSM uses a different endpoint than the AWS default. This can be useful for local development when you are running something like `LocalStack `_.
- ``SSM_SESSION_FOR_DYNACONF``: If you require custom `boto3.session.Session `_ arguments, you can specify then as a dictionary here. Note that this will override the default ``boto3`` credential configuration.
- ``SSM_LOAD_DEFAULT_ENV_FOR_DYNACONF``: Boolean, defaults to ``True``. If you want the SSM loader to load keys under the ``default`` environment name. The key name itself can be set via the Dynaconf setting of ``DEFAULT_ENV_FOR_DYNACONF`` if you want it to be something other than ``default``.Parameter Store Details
~~~~~~~~~~~~~~~~~~~~~~~The structure that this loader expects from the path-based organization in SSM is:
.. code-block::
///
An optional ``namespace`` can be specified as a sub-project grouping for parameters:
.. code-block::
////
Note that if you choose to use a ``namespace`` identifier, it must not conflict with existing ``environment`` identifiers.
If ``SSM_LOAD_DEFAULT_ENV_FOR_DYNACONF`` is set to ``True`` (which is the default value), the loader will add whatever the value of ``DEFAULT_ENV_FOR_DYNACONF`` as an ``environment`` key to load from SSM. The typical use case here is to have a default value for all environments that can be overriden on a per-environment basis as necessary.
Security Considerations
~~~~~~~~~~~~~~~~~~~~~~~For this loader to function correctly and securely, the use of IAM policies to restrict which parameters can be read/mutated is highly encouraged.
Policies can be enacted on a glob-path basis, which will ensure that the only parameters that can be fetched/hydrated into the local object instance are the ones that the current environment is permitted to load.
The following policy for a fictional account allows a user to call the ``DescribeParameters`` and ``GetParameters`` API operations for parameters that begin with the path ``/testapp/production``:
.. code-block:: json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:DescribeParameters"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ssm:GetParameters"
],
"Resource": "arn:aws:ssm:us-east-1:000000000000:parameter/testapp/production*"
}
]
}.. warning::
If a user has access to a path, then the user can access all levels of that path. For example, if a user has permission to access path ``/testapp``, then the user can also access ``testapp/production``. Even if a user has explicitly been denied access in IAM for parameter ``/testapp/production``, they can still call the ``GetParametersByPath`` API operation recursively for ``/testapp`` and view ``/testapp/production``.
Setting Parameters via Boto3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~Parameters may be set via the AWS Web Console UI, or one of their many client libraries. The `boto3 `_ library is perhaps the most well-known, and the process is relatively straightforward:
.. code-block:: python
import boto3
ssm_client = boto3.client("ssm")ssm_client.put_parameter(
Name="/testapp/development/database/host",
Value="localhost",
Type="String",
)ssm_client.put_parameter(
Name="/testapp/production/database/password",
Value="sekrit",
Type="SecureString",
)ssm_client.put_parameter(
Name="/testapp/production/database/host",
Value="db.example.com",
Type="String",
)ssm_client.put_parameter(
Name="/testapp/production/admin_email",
Value="[email protected]",
Type="String",
)This creates a parameter hierarchy with the following structure:
.. code-block:: json
{
"testapp": {
"development": {"database": {"host": "localhost"}},
"production": {
"database": {"host": "db.example.com", "password": "sekrit"},
"admin_email": "[email protected]",
},
},
}Parameter Name Limitations
--------------------------AWS SSM has the following key (and thus path) limitations:
- Parameter names are case sensitive
- A parameter name must be unique within an Amazon Web Services Region
- A parameter name can't be prefixed with "aws" or "ssm" (case-insensitive)
- Parameter names can include only the following symbols and letters: a-zA-Z0-9\_.-
- The slash character ( ``/`` ) is used to delineate hierarchies in parameter names
- A parameter name can't include spaces
- Parameter hierarchies are limited to a maximum depth of fifteen levelsTesting
~~~~~~~0. Have Docker installed and running
1. Clone this repository
2. Ensure you have `poetry` available on your system
3. `poetry run pytest`The test suite will spin up an ephemeral Docker container; it may take a few seconds for it to load. The relevant test fixtures will handle setting parameters and their values in the Localstack SSM service.
TODO
~~~~- [ ] CI configuration for matrix-based python/dynaconf version testing
- [ ] Handle `Parameter Store references to AWS Secrets Manager `_
- [ ] Make ``tests/docker-compose.yml`` more configurable, e.g. ports, in case a different Localstack container is already running for the user