Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
ConfMe is a simple to use, production ready application configuration management library, which takes into consideration the following three thoughts:
myconfig['value1']['subvalue']
anymore!ConfMe makes all these features possible with just a few type annotations on plain Python objects.
ConfMe can be installed from the official python package repository pypi
pip install confme
Or, if you're using pipenv:
pipenv install confme
Or, if you're using poetry:
poetry add confme
Define your config structure as plain python objects with type annotations:
from confme import BaseConfig
class DatabaseConfig(BaseConfig):
host: str
port: int
user: str
class MyConfig(BaseConfig):
name: str
database: DatabaseConfig
Create a configuration yaml file with the same structure as your configuration classes have:
name: "Database Application"
database:
host: "localhost"
port: 5000
user: "any-db-user"
Load the yaml file into your Python object structure and access it in a secure manner:
my_config = MyConfig.load('config.yaml')
print(f'Using database connection {my_config.database.host} '
f'on port {my_config.database.port}')
In the background the yaml file is parsed and mapped to the defined object structure. While mapping the values to object properties, type checks are performed. If a value is not available or is not of the correct type, an error is generated already when the configuration is loaded.
ConfMe is based on pydantic and supports all annotations provided by pydantic. The most important annotations are listed and explain bellow. For the whole list, please checkout Field Types:
With the Secret annotation you can inject secrets from environment variables directly into your configuration structure. This is especially handy when you're deploying applications by using docker. Therefore, let's extend the previous example with a Secret annotation:
from confme import BaseConfig
from confme.annotation import Secret
class DatabaseConfig(BaseConfig):
...
password: str = Secret('highSecurePassword')
Now set the password to the defined environment variable:
export highSecurePassword="This is my password"
Load your config and check for the injected password.
my_config = MyConfig.load('config.yaml')
print(f'My password is: {my_config.database.password}')
ConfME supports OpenRange, ClosedRange and MixedRange values. The terms open and close are similar to open and closed intervals in mathematics. This means, if you want to include the lower and upper range use ClosedRange otherwise OpenRange:
ClosedRange(2, 3)
will include 2 and 3OpenRange(2, 3)
will not include 2 and 3If you want to have a mixture of both, e.g. include 2 but exclude 3 use MixedRange:
MixedRange(ge=2, lt=3)
will include 2 but exclude 3from confme import BaseConfig
from confme.annotation import ClosedRange
class DatabaseConfig(BaseConfig):
...
password: int = ClosedRange(2, 3)
If a Python Enum is set as type annotation, ConfMe expect to find the enum value in the configuration file.
from confme import BaseConfig
from enum import Enum
class DatabaseConnection(Enum):
TCP = 'tcp'
UDP = 'udp'
class DatabaseConfig(BaseConfig):
...
connection_type: DatabaseConnection
A very common situation is that configurations must be changed based on the execution environment (dev, test, prod). This can be accomplished
by registering a folder with one .yaml file per environment and seting the ENV
environment variable to the value you need. An example could look
like this:
Let's assume we have three environments (dev, test, prod) and one configuration file per environment in the following folder structure:
project
│
└───config
│ │ my_prod_config.yaml
│ │ my_test_config.yaml
│ │ my_dev_config.yaml
│
└───src
│ │ app.py
│ │ my_config.py
The definition of my_config.py
is equivalent to the one used in the basic introduction section and app.py
uses our configuration the
following way:
# we register the folder where ConfME can find the configuration files
MyConfig.register_folder(Path(__file__).parent / '../config')
...
# we access the instance of the corresponding configuration file anywhere in our project.
my_config = MyConfig.get()
print(f'Using database connection {my_config.database.host} '
f'on port {my_config.database.port}')
If now one of the following environment variables (precedence in descending order): ['env', 'environment', 'environ', 'stage']
is
set e.g. export ENV=prod
it will load the configuration file with prod
in its name.
In addition to loading configuration parameters from the configuration file, they can be passed/overwritten from the command line or environment variables. Thereby, the following precedences apply (lower number means higher precedence):
Especially in the Data Science and Machine Learning area it is useful to pass certain parameters for experimental purposes as command line arguments. Therefore, all properties defined in the configuration classes are automatically offered as command line arguments in the following format:
my_program.py:
from confme import BaseConfig
class DatabaseConfig(BaseConfig):
host: str
port: int
user: str
class MyConfig(BaseConfig):
name: int
database: DatabaseConfig
config = MyConfig.load('test.yaml')
When you now start your program from the command line with the ++help
argument, you get the full list of all configuration options. CAVEAT! In order to not interfere with other cli tools, the prefix - was changed to +:
$ python my_program.py --help
usage: my_program.py [+h] [++name NAME] [++database.host DATABASE.HOST] [++database.port DATABASE.PORT] [++database.user DATABASE.USER]
optional arguments:
+h, ++help show this help message and exit
Configuration Parameters:
With the parameters specified bellow, the configuration values from the config file can be overwritten.
++name NAME
++database.host DATABASE.HOST
++database.port DATABASE.PORT
++database.user DATABASE.USER
Likewise to overwriting parameters from the commandline you can also overwrite by passing environment variables. Therefore, simply set the environment variable in the same format as it would be passed as command line arguments and run your application:
$ export database.host=localhost
$ python my_programm.py
Pydantic is the underlying library powering ConfMe and with the update to pydantic v2 some breaking changes where introduced. However, we tried our best to minimize the impact on your project and only passed a selection of changes to you. Please find these documented bellow:
Pydantic V2 changes some of the logic for specifying whether a field annotated as Optional is required (i.e., has no default value) or not (i.e., has a default value of None or any other value of the corresponding type), and now more closely matches the behavior of dataclasses. Similarly, fields annotated as Any no longer have a default value of None.
The following table describes the behavior of field annotations in V2:
State | Field Definition |
---|---|
Required, cannot be None | f1: str |
Not required, cannot be None , is 'abc' by default | f3: str = 'abc' |
Required, can be None | f2: Optional[str] |
Not required, can be None , is None by default | f3: Optional[str] = None |
Not required, can be None , is 'abc' by default | f3: Optional[str] = 'abc' |
Not required, cannot be None | f4: str = 'Foobar' |
Required, can be any type (including None ) | f5: Any |
Not required, can be any type (including None ) | f6: Any = None |
ConfMe is released under the MIT license.
FAQs
Easy configuration management in python
We found that confme demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.