Created
February 17, 2022 14:16
-
-
Save sergioisidoro/7972229bb5826c25f12e7a406f11e7cd to your computer and use it in GitHub Desktop.
A python class for accessing docker secrets like environment variables, with fallback to os.environ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
class DockerSecrets(object): | |
""" | |
Facilitates the usage of docker secrets, by parsing all files into | |
an digestible object, without ever them touching the environment, | |
which would be bad because they might be stored in docker layers, or | |
accessed by other linked containers. All secret keys are transformed | |
into snake case upper case. | |
# If there's a file in /run/secrets/secret-key, their contents will be | |
# accessible like so: | |
secrets = DockerSecrets() | |
super_secret = secrets('SECRET_KEY') | |
""" | |
BOOLEAN_TRUE_STRINGS = ('true', 'on', 'ok', 'y', 'yes', '1') | |
SECRETS = {} | |
def file_name_to_variable_name(self, name): | |
""" | |
Turns a file name like 'file-name` to FILE_NAME | |
""" | |
return name.replace(" ", "_").replace("-", "_").upper() | |
def __init__( | |
self, | |
docker_secrets_path="/run/secrets/", | |
fallback_to_env=False, | |
environ_object=None | |
) -> None: | |
if environ_object is None: | |
self.environ_object = os.environ | |
else: | |
self.environ_object = environ_object | |
self.fallback_to_env = fallback_to_env | |
if os.path.exists(docker_secrets_path): | |
secrets = os.listdir(docker_secrets_path) | |
else: | |
secrets = [] | |
for secret_file_name in secrets: | |
full_secret_file_path = os.path.join( | |
docker_secrets_path, | |
secret_file_name | |
) | |
with open(full_secret_file_path) as secret_file: | |
key = self.file_name_to_variable_name(secret_file_name) | |
self.SECRETS[key] = secret_file.read() | |
def __call__(self, var, cast=None, default=None): | |
return self.get_value( | |
var, cast, default | |
) | |
def get_value(self, var, cast=None, default=None): | |
if var in self.SECRETS: | |
value = self.SECRETS[var] | |
elif self.fallback_to_env: | |
value = self.environ_object.get(var) | |
else: | |
value = default | |
if cast is not None: | |
value = self.parse_value(value, cast) | |
return value | |
@classmethod | |
def parse_value(cls, value, cast): | |
if cast is None: | |
return value | |
elif cast is bool: | |
try: | |
value = int(value) != 0 | |
except ValueError: | |
value = value.lower() in cls.BOOLEAN_TRUE_STRINGS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment