diff --git a/src/cnaas_nms/confpush/sync_devices.py b/src/cnaas_nms/confpush/sync_devices.py index 4e8f688a..3e248efc 100644 --- a/src/cnaas_nms/confpush/sync_devices.py +++ b/src/cnaas_nms/confpush/sync_devices.py @@ -15,6 +15,7 @@ from cnaas_nms.db.session import sqla_session, redis_session from cnaas_nms.confpush.get import calc_config_hash from cnaas_nms.confpush.changescore import calculate_score +from cnaas_nms.tools.jinja_helpers import get_environment_secrets from cnaas_nms.tools.log import get_logger from cnaas_nms.db.settings import get_settings from cnaas_nms.db.device import Device, DeviceState, DeviceType @@ -316,10 +317,7 @@ def populate_device_vars(session, dev: Device, # Add all environment variables starting with TEMPLATE_SECRET_ to # the list of configuration variables. The idea is to store secret # configuration outside of the templates repository. - template_secrets = {} - for env in os.environ: - if env.startswith('TEMPLATE_SECRET_'): - template_secrets[env] = os.environ[env] + template_secrets = get_environment_secrets() # Merge all dicts with variables into one, later row overrides # Device variables override any names from settings, for example the # interfaces list from settings are replaced with an interface list from diff --git a/src/cnaas_nms/tools/jinja_helpers.py b/src/cnaas_nms/tools/jinja_helpers.py new file mode 100644 index 00000000..eb02011f --- /dev/null +++ b/src/cnaas_nms/tools/jinja_helpers.py @@ -0,0 +1,13 @@ +"""Functions that aid in the building of Jinja template contexts""" +import os + + +def get_environment_secrets(prefix="TEMPLATE_SECRET_"): + """Returns a dictionary of secrets stored in environment variables""" + template_secrets = {env: value for env, value in os.environ.items() if env.startswith(prefix)} + # Also make secrets available as a dict, so keys can be constructed dynamically in templates + template_secrets["TEMPLATE_SECRET"] = { + env.replace(prefix, ""): value for env, value in template_secrets.items() + } + + return template_secrets diff --git a/src/cnaas_nms/tools/template_dry_run.py b/src/cnaas_nms/tools/template_dry_run.py index b0442d5c..f8d8fd0d 100755 --- a/src/cnaas_nms/tools/template_dry_run.py +++ b/src/cnaas_nms/tools/template_dry_run.py @@ -3,6 +3,9 @@ import sys import os import argparse + +from jinja_helpers import get_environment_secrets + try: import requests import jinja2 @@ -74,11 +77,7 @@ def render_template(platform, device_type, variables): for f in jfilters: jinjaenv.filters[f] = jfilters[f] print("Jinja filters added: {}".format([*jfilters])) - template_secrets = {} - for env in os.environ: - if env.startswith('TEMPLATE_SECRET_'): - template_secrets[env] = os.environ[env] - template_vars = {**variables, **template_secrets} + template_vars = {**variables, **get_environment_secrets()} template = jinjaenv.get_template(get_entrypoint(platform, device_type)) return template.render(**template_vars) diff --git a/src/cnaas_nms/tools/tests/test_jinja_helpers.py b/src/cnaas_nms/tools/tests/test_jinja_helpers.py new file mode 100644 index 00000000..b956cba1 --- /dev/null +++ b/src/cnaas_nms/tools/tests/test_jinja_helpers.py @@ -0,0 +1,33 @@ +import os +import unittest + +from cnaas_nms.tools.jinja_helpers import get_environment_secrets + + +class EnvironmentSecretsTest(unittest.TestCase): + def setUp(self) -> None: + os.environ['TEMPLATE_SECRET_FOO'] = 'bar' + os.environ['TEMPLATE_SECRET_TEST_TYPE'] = 'cromulent' + os.environ['NOT_A_SECRET'] = 'foobar' + + def tearDown(self) -> None: + del os.environ['TEMPLATE_SECRET_FOO'] + del os.environ['TEMPLATE_SECRET_TEST_TYPE'] + del os.environ['NOT_A_SECRET'] + + def test_that_individual_secrets_are_present(self): + secrets = get_environment_secrets() + self.assertEquals(secrets['TEMPLATE_SECRET_FOO'], 'bar') + self.assertEquals(secrets['TEMPLATE_SECRET_TEST_TYPE'], 'cromulent') + + def test_that_secret_dict_is_set_properly(self): + secrets = get_environment_secrets() + self.assertIn('TEMPLATE_SECRET', secrets) + + secret_dict = secrets.get('TEMPLATE_SECRET') + self.assertEquals(secret_dict['FOO'], 'bar') + self.assertEquals(secret_dict['TEST_TYPE'], 'cromulent') + + def test_that_non_secret_variables_arent_included(self): + secrets = get_environment_secrets() + self.assertNotIn('NOT_A_SECRET', secrets)