Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/contacts/contact_gist.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def retrieve_config(self):
return self.token

async def start(self):
token = self.get_config('app.contact.gist', '').strip()
token = (self.get_secret('app.contact.gist', env_var='CALDERA_GIST_TOKEN') or '').strip()
if token:
if self.valid_config(token):
self.token = token
Expand Down
6 changes: 3 additions & 3 deletions app/contacts/contact_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ def retrieve_config(self):

async def start(self):
if await self.valid_config():
self.key = self.get_config('app.contact.slack.api_key')
self.channelid = self.get_config('app.contact.slack.channel_id')
self.botid = self.get_config('app.contact.slack.bot_id')
self.key = self.get_secret('app.contact.slack.api_key', env_var='CALDERA_SLACK_API_KEY')
self.channelid = self.get_secret('app.contact.slack.channel_id')
self.botid = self.get_secret('app.contact.slack.bot_id')
loop = asyncio.get_event_loop()
loop.create_task(self.slack_operation_loop())

Expand Down
21 changes: 21 additions & 0 deletions app/utility/base_world.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import binascii
import os
import string
import re
import yaml
Expand Down Expand Up @@ -46,6 +47,26 @@ def set_config(name, prop, value):
logging.debug('Configuration (%s) update, setting %s=%s' % (name, prop, value))
BaseWorld._app_configuration[name][prop] = value

@staticmethod
def get_secret(key, env_var=None):
"""Retrieve a secret value, checking environment variables first, then config.

Args:
key: The config key to look up.
env_var: Optional environment variable name to check first.

Returns:
The secret value from env var or config, or None if neither found.
"""
if env_var:
env_value = os.environ.get(env_var)
if env_value:
return env_value
try:
return BaseWorld.get_config(key)
except KeyError:
return None

@staticmethod
def decode_bytes(s, strip_newlines=True):
decoded = b64decode(s).decode('utf-8', errors='ignore')
Expand Down
2 changes: 2 additions & 0 deletions conf/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ api_key_blue: BLUEADMIN123
api_key_red: ADMIN123
app.contact.dns.domain: mycaldera.caldera
app.contact.dns.socket: 0.0.0.0:8853
# Override with env var CALDERA_GIST_TOKEN
app.contact.gist: API_KEY
app.contact.html: /weather
app.contact.http: http://0.0.0.0:8888
# Override with env var CALDERA_SLACK_API_KEY
app.contact.slack.api_key: SLACK_TOKEN
app.contact.slack.bot_id: SLACK_BOT_ID
app.contact.slack.channel_id: SLACK_CHANNEL_ID
Expand Down
36 changes: 36 additions & 0 deletions tests/test_get_secret.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import pytest
from app.utility.base_world import BaseWorld


@pytest.fixture
def setup_config():
BaseWorld.apply_config('main', {'app.contact.gist': 'config_token', 'app.contact.slack.api_key': 'config_slack'})
yield
BaseWorld.clear_config()


class TestGetSecret:
def test_env_var_takes_priority(self, setup_config):
os.environ['CALDERA_GIST_TOKEN'] = 'env_token'
try:
result = BaseWorld.get_secret('app.contact.gist', env_var='CALDERA_GIST_TOKEN')
assert result == 'env_token'
finally:
del os.environ['CALDERA_GIST_TOKEN']

def test_falls_back_to_config(self, setup_config):
result = BaseWorld.get_secret('app.contact.gist')
assert result == 'config_token'

def test_returns_none_when_neither(self, setup_config):
result = BaseWorld.get_secret('nonexistent.key', env_var='NONEXISTENT_ENV_VAR')
assert result is None

def test_env_var_empty_string_falls_back(self, setup_config):
os.environ['CALDERA_GIST_TOKEN'] = ''
try:
result = BaseWorld.get_secret('app.contact.gist', env_var='CALDERA_GIST_TOKEN')
assert result == 'config_token'
finally:
del os.environ['CALDERA_GIST_TOKEN']
Loading