[fix] Handles quotes in JSON path for substitution

This is to fix a use case where a subpath like 'filter:authtoken' in
a JSON path like ".values.conf.paste.'filter:authtoken'.password" fails
because the resulting Python object that is created in memory
for substitution constructs a dict key like "'filter:authtoken'" resulting
in Deckhand failing to index into the dict as the key needs to be
stripped of start and end quotes that are only necessary for achieving
valid YAML syntax.

A unit test is added for regression.

Change-Id: I19974efc977b0cdc5793e649fa068d1a3bd7339e
This commit is contained in:
Felipe Monteiro 2018-04-26 18:48:57 +01:00 committed by Bryan Strassner
parent e65710bf1a
commit a5bb91bc76
3 changed files with 43 additions and 2 deletions

View File

@ -128,6 +128,10 @@ def _populate_data_with_attributes(jsonpath, data):
pass
# Handle case where an object needs to be created.
elif path not in d:
if '\'' or '\"' in path:
LOG.info('Stripping subpath %s of start and end quotes during '
'path vivification for jsonpath: %s.', path, jsonpath)
path = path.strip('\'').strip('\"')
d.setdefault(path, {})
d = d.get(path)

View File

@ -397,8 +397,8 @@ class SecretsSubstitution(object):
exc_message = (
'Failed to create JSON path "%s" in the '
'destination document [%s, %s] %s. No data was '
'substituted.', dest_path, document.schema,
document.layer, document.name)
'substituted.' % (dest_path, document.schema,
document.layer, document.name))
except Exception as e:
LOG.error('Unexpected exception occurred while attempting '
'substitution using source document [%s, %s] %s '

View File

@ -362,6 +362,43 @@ class TestSecretsSubstitution(test_base.TestDbBase):
self._test_doc_substitution(
document_mapping, [certificate], expected_data)
def test_create_destination_with_stringified_subpath(self):
"""Validate that a subpath like 'filter:authtoken' in a JSON path like
".values.conf.paste.'filter:authtoken'.password" works correctly.
"""
certificate = self.secrets_factory.gen_test(
'Passphrase', 'cleartext', data='admin-passphrase')
certificate['metadata']['name'] = 'example-passphrase'
document_mapping = {
"_GLOBAL_SUBSTITUTIONS_1_": [{
"dest": {
# NOTE(fmontei): Usage of special characters like this
# without quotes need not be handled because it is not
# valid YAML to include ":" without quotes.
"path": ".values.conf.paste.'filter:authtoken'.password"
},
"src": {
"schema": "deckhand/Passphrase/v1",
"name": "example-passphrase",
"path": "."
}
}]
}
expected_data = {
'values': {
'conf': {
'paste': {
'filter:authtoken': {
'password': 'admin-passphrase'
}
}
}
}
}
self._test_doc_substitution(
document_mapping, [certificate], expected_data)
def test_doc_substitution_single_cleartext_with_pattern(self):
passphrase = self.secrets_factory.gen_test(
'Passphrase', 'cleartext', data='my-secret-password')