Skip to content

Commit

Permalink
Add keys to environment variable
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Martin Cantalejo authored and Stranger6667 committed Jan 14, 2020
1 parent 4ce5c2d commit 59685c9
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Changelog
`Unreleased`_
-------------

Added
~~~~~
- Add keys to environment variable name before search in Vault.

Fixed
~~~~~
- Change Flask KonfigProxy to behave like Flask config.
Expand Down
33 changes: 21 additions & 12 deletions src/konfetti/vault/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,31 @@ def evaluate(self, backend, closure):

def _try_load_from_env(self, backend):
# type: (VaultBackend) -> Any
value = EnvVariable(self.override_variable_name, cast=self.cast).evaluate()
try:
value = self._try_load_dict_from_env()
except exceptions.MissingError:
value = EnvVariable(self.override_variable_name(add_keys=True), cast=self.cast).evaluate()

if backend.is_async:
from .._async import make_simple_coro # pylint: disable=import-outside-toplevel

value = make_simple_coro(value)
return value

def _try_load_dict_from_env(self):
value = EnvVariable(self.override_variable_name(), cast=self.cast).evaluate()
try:
value = json.loads(value)
except (ValueError, TypeError):
pass
if not isinstance(value, dict):
raise exceptions.InvalidSecretOverrideError(
"`{}` variable should be a JSON-encoded dictionary, got: `{}`".format(
self.override_variable_name, value
self.override_variable_name(), value
)
)
for key in self.keys:
value = value[key]

if backend.is_async:
from .._async import make_simple_coro # pylint: disable=import-outside-toplevel

value = make_simple_coro(value)
return value

def _load_credentials(self, closure):
Expand Down Expand Up @@ -141,9 +148,8 @@ def disabled(self):
# Move to some global config or we need to modify in runtime?
return EnvVariable(SECRETS_DISABLED_VARIABLE, default=False, cast=bool).evaluate()

@property
def override_variable_name(self):
# type: () -> str
def override_variable_name(self, add_keys=False):
# type: (bool) -> str
"""Convert path to a name of environment variable that will be checked for overriding.
If some key in that secret is going to be overridden then its name is concatenated
Expand All @@ -152,7 +158,10 @@ def override_variable_name(self):
Example:
config.vault("path/to") -> "PATH__TO"
"""
return self.path.strip("/").replace("/", SEPARATOR).upper()
path = self.path.strip("/")
if add_keys:
path = "/".join([path] + self.keys)
return path.replace("/", SEPARATOR).upper()

@property
def override_example(self):
Expand All @@ -168,4 +177,4 @@ def override_example(self):
value = json.dumps(example)
else:
value = "{}"
return {self.override_variable_name: value}
return {self.override_variable_name(): value}
13 changes: 11 additions & 2 deletions test/test_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,19 @@ def test_get_secret_without_vault_credentials(config, monkeypatch, variables):
config.get_secret("/path/to")


@pytest.mark.parametrize("path, keys, expected", (("/path/to/", ["SECRET"], "PATH__TO"), ("path/to", [], "PATH__TO")))
@pytest.mark.parametrize(
"path, keys, expected",
(
("/path/to/", ["SECRET"], {"no_keys": "PATH__TO", "keys": "PATH__TO__SECRET"}),
("path/to", [], {"no_keys": "PATH__TO", "keys": "PATH__TO"}),
),
)
def test_override_variable_name(path, keys, expected):
variable = VaultVariable(path)
for key in keys:
variable = variable[key]
assert variable.override_variable_name == expected
assert variable.override_variable_name() == expected["no_keys"]
assert variable.override_variable_name(add_keys=True) == expected["keys"]


def test_path_not_string():
Expand Down Expand Up @@ -141,8 +148,10 @@ def test_override_secret(config, monkeypatch):

def test_override_config_secret(config, monkeypatch):
monkeypatch.setenv("PATH__TO", '{"SECRET": "bar"}')
monkeypatch.setenv("PATH__TO__NESTED__NESTED_SECRET__NESTED", "test")
assert config.WHOLE_SECRET == {"SECRET": "bar"}
assert config.SECRET == "bar"
assert config.NESTED_SECRET == "test"


@pytest.mark.parametrize("data", ("[1, 2]", "[invalid]"))
Expand Down

0 comments on commit 59685c9

Please sign in to comment.