Skip to content

Instantly share code, notes, and snippets.

@sergioisidoro
Created February 17, 2022 14:16
Show Gist options
  • Save sergioisidoro/7972229bb5826c25f12e7a406f11e7cd to your computer and use it in GitHub Desktop.
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
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