Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed a problem not to decrypt user scope data store value in Jinja expression #4634

Merged
merged 11 commits into from
Apr 16, 2019
4 changes: 2 additions & 2 deletions st2common/st2common/expressions/functions/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from __future__ import absolute_import
from oslo_config import cfg

from st2common.services.keyvalues import KeyValueLookup
from st2common.services.keyvalues import KeyValueLookup, UserKeyValueLookup
from st2common.util.crypto import read_crypto_key, symmetric_decrypt

__all__ = [
Expand All @@ -25,7 +25,7 @@


def decrypt_kv(value):
if isinstance(value, KeyValueLookup):
if isinstance(value, KeyValueLookup) or isinstance(value, UserKeyValueLookup):
# Since this is a filter the incoming value is still a KeyValueLookup
# object as the jinja rendering is not yet complete. So we cast
# the KeyValueLookup object to a simple string before decrypting.
Expand Down
45 changes: 36 additions & 9 deletions st2common/tests/unit/test_jinja_render_crypto_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,35 @@
from oslo_config import cfg

from st2tests.base import CleanDbTestCase
from st2common.constants.keyvalue import FULL_SYSTEM_SCOPE, SYSTEM_SCOPE, DATASTORE_PARENT_SCOPE
from st2common.constants.keyvalue import (
FULL_SYSTEM_SCOPE,
SYSTEM_SCOPE,
DATASTORE_PARENT_SCOPE,
FULL_USER_SCOPE,
USER_SCOPE,
)
from st2common.models.db.keyvalue import KeyValuePairDB
from st2common.persistence.keyvalue import KeyValuePair
from st2common.services.keyvalues import KeyValueLookup
from st2common.services.keyvalues import KeyValueLookup, UserKeyValueLookup
from st2common.util import jinja as jinja_utils
from st2common.util.crypto import read_crypto_key, symmetric_encrypt


class JinjaUtilsDecryptTestCase(CleanDbTestCase):
def setUp(self):
super(JinjaUtilsDecryptTestCase, self).setUp()

def test_filter_decrypt_kv(self):
secret = 'Build a wall'
crypto_key_path = cfg.CONF.keyvalue.encryption_key_path
crypto_key = read_crypto_key(key_path=crypto_key_path)
secret_value = symmetric_encrypt(encrypt_key=crypto_key, plaintext=secret)
KeyValuePair.add_or_update(KeyValuePairDB(name='k8', value=secret_value,

self.secret = 'Build a wall'
self.secret_value = symmetric_encrypt(encrypt_key=crypto_key, plaintext=self.secret)
self.env = jinja_utils.get_jinja_environment()

def test_filter_decrypt_kv(self):
KeyValuePair.add_or_update(KeyValuePairDB(name='k8', value=self.secret_value,
scope=FULL_SYSTEM_SCOPE,
secret=True))
env = jinja_utils.get_jinja_environment()

context = {}
context.update({SYSTEM_SCOPE: KeyValueLookup(scope=SYSTEM_SCOPE)})
Expand All @@ -46,5 +56,22 @@ def test_filter_decrypt_kv(self):
})

template = '{{st2kv.system.k8 | decrypt_kv}}'
actual = env.from_string(template).render(context)
self.assertEqual(actual, secret)
actual = self.env.from_string(template).render(context)
self.assertEqual(actual, self.secret)

def test_filter_decrypt_kv_with_user_scope_value(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also be a good idea to add "end to end" test which verifies that it works for the following scenarios:

  1. API user is provided (if action is scheduled via API, API user should be used)
  2. User is not provided - it should default to stanley (if execution is scheduled outside of the API context, no user context is available so stanley is used by default)

KeyValuePair.add_or_update(KeyValuePairDB(name='stanley:k8', value=self.secret_value,
scope=FULL_USER_SCOPE,
secret=True))

context = {}
context.update({USER_SCOPE: UserKeyValueLookup(user='stanley', scope=USER_SCOPE)})
context.update({
DATASTORE_PARENT_SCOPE: {
USER_SCOPE: UserKeyValueLookup(user='stanley', scope=FULL_USER_SCOPE)
}
})

template = '{{st2kv.user.k8 | decrypt_kv}}'
actual = self.env.from_string(template).render(context)
self.assertEqual(actual, self.secret)