summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLev Morgan <morgan.lev@gmail.com>2019-02-04 15:50:23 -0600
committerLev Morgan <morgan.lev@gmail.com>2019-03-05 16:48:46 +0000
commit0252b7175067e1bc6badd808d34390989b9ea43f (patch)
treede79c0bfbd72e37c77fb299d8d1e560006c76aeb
parent81720cd0c8053c0499f9b66b17d8ed29fd531c0d (diff)
Search all scopes for catalogs
This patch revises pegleg to check all scopes for catalog files, rather than just the site scope. Change-Id: Icf03ce739968ef3ed5fd218ca0fe87e24451ba0d
Notes
Notes (review): Code-Review+2: Aaron Sheffield <ajs@sheffieldfamily.net> Code-Review+1: Alexander Hughes <Alexander.Hughes@pm.me> Code-Review+1: Stacey Fletcher <staceylynnfletcher@gmail.com> Code-Review+2: Bryan Strassner <strassner.bryan@gmail.com> Workflow+1: Bryan Strassner <strassner.bryan@gmail.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Wed, 06 Mar 2019 14:53:53 +0000 Reviewed-on: https://review.openstack.org/634821 Project: openstack/airship-pegleg Branch: refs/heads/master
-rw-r--r--pegleg/engine/catalogs/base_catalog.py22
-rw-r--r--tests/unit/engine/test_generate_cryptostring.py76
2 files changed, 82 insertions, 16 deletions
diff --git a/pegleg/engine/catalogs/base_catalog.py b/pegleg/engine/catalogs/base_catalog.py
index 01aaa32..58b07a7 100644
--- a/pegleg/engine/catalogs/base_catalog.py
+++ b/pegleg/engine/catalogs/base_catalog.py
@@ -14,7 +14,6 @@
14 14
15from abc import ABC 15from abc import ABC
16import logging 16import logging
17import os
18import re 17import re
19 18
20from pegleg import config 19from pegleg import config
@@ -43,7 +42,7 @@ class BaseCatalog(ABC):
43 """ 42 """
44 self._documents = documents or definition.documents_for_site(sitename) 43 self._documents = documents or definition.documents_for_site(sitename)
45 self._site_name = sitename 44 self._site_name = sitename
46 self._catalog_path = None 45 self._catalog_path = []
47 self._kind = kind 46 self._kind = kind
48 self._catalog_docs = list() 47 self._catalog_docs = list()
49 for document in self._documents: 48 for document in self._documents:
@@ -61,7 +60,7 @@ class BaseCatalog(ABC):
61 60
62 @property 61 @property
63 def catalog_path(self): 62 def catalog_path(self):
64 if self._catalog_path is None: 63 if not self._catalog_path:
65 self._set_catalog_path() 64 self._set_catalog_path()
66 return self._catalog_path 65 return self._catalog_path
67 66
@@ -69,15 +68,14 @@ class BaseCatalog(ABC):
69 repo_name = git.repo_url(config.get_site_repo()) 68 repo_name = git.repo_url(config.get_site_repo())
70 catalog_name = self._get_document_name('{}.yaml'.format(self._kind)) 69 catalog_name = self._get_document_name('{}.yaml'.format(self._kind))
71 for file_path in definition.site_files(self.site_name): 70 for file_path in definition.site_files(self.site_name):
72 if file_path.endswith(catalog_name) and repo_name in file_path: 71 if file_path.endswith(catalog_name):
73 self._catalog_path = os.path.join( 72 self._catalog_path.append(file_path)
74 repo_name, file_path.split(repo_name)[1].lstrip('/')) 73 if not self._catalog_path:
75 return 74 # Cound not find the Catalog for this generated passphrase
76 # Cound not find the Catalog for this generated passphrase 75 # raise an exception.
77 # raise an exception. 76 LOG.error('Catalog path: {} was not found in repo: {}'.format(
78 LOG.error('Catalog path: {} was not found in repo: {}'.format( 77 catalog_name, repo_name))
79 catalog_name, repo_name)) 78 raise PassphraseCatalogNotFoundException()
80 raise PassphraseCatalogNotFoundException()
81 79
82 def _get_document_name(self, name): 80 def _get_document_name(self, name):
83 s1 = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', name) 81 s1 = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', name)
diff --git a/tests/unit/engine/test_generate_cryptostring.py b/tests/unit/engine/test_generate_cryptostring.py
index c05bb8b..4e9576f 100644
--- a/tests/unit/engine/test_generate_cryptostring.py
+++ b/tests/unit/engine/test_generate_cryptostring.py
@@ -69,6 +69,24 @@ data:
69... 69...
70""") 70""")
71 71
72TEST_GLOBAL_PASSPHRASES_CATALOG = yaml.load("""
73---
74schema: pegleg/PassphraseCatalog/v1
75metadata:
76 schema: metadata/Document/v1
77 name: cluster-passphrases
78 layeringDefinition:
79 abstract: false
80 layer: global
81 storagePolicy: cleartext
82data:
83 passphrases:
84 - description: 'description of passphrase from global'
85 document_name: passphrase_from_global
86 encrypted: true
87...
88""")
89
72TEST_REPOSITORIES = { 90TEST_REPOSITORIES = {
73 'repositories': { 91 'repositories': {
74 'global': { 92 'global': {
@@ -101,6 +119,7 @@ TEST_SITE_DEFINITION = {
101} 119}
102 120
103TEST_SITE_DOCUMENTS = [TEST_SITE_DEFINITION, TEST_PASSPHRASES_CATALOG] 121TEST_SITE_DOCUMENTS = [TEST_SITE_DEFINITION, TEST_PASSPHRASES_CATALOG]
122TEST_GLOBAL_SITE_DOCUMENTS = [TEST_SITE_DEFINITION, TEST_GLOBAL_PASSPHRASES_CATALOG]
104 123
105 124
106def test_cryptostring_default_len(): 125def test_cryptostring_default_len():
@@ -149,13 +168,13 @@ def test_cryptostring_long_len():
149 ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC', 168 ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
150 ENV_SALT: 'MySecretSalt'}) 169 ENV_SALT: 'MySecretSalt'})
151def test_generate_passphrases(*_): 170def test_generate_passphrases(*_):
152 dir = tempfile.mkdtemp() 171 _dir = tempfile.mkdtemp()
153 os.makedirs(os.path.join(dir, 'cicd_site_repo'), exist_ok=True) 172 os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)
154 PassphraseGenerator('cicd', dir, 'test_author').generate() 173 PassphraseGenerator('cicd', _dir, 'test_author').generate()
155 174
156 for passphrase in TEST_PASSPHRASES_CATALOG['data']['passphrases']: 175 for passphrase in TEST_PASSPHRASES_CATALOG['data']['passphrases']:
157 passphrase_file_name = '{}.yaml'.format(passphrase['document_name']) 176 passphrase_file_name = '{}.yaml'.format(passphrase['document_name'])
158 passphrase_file_path = os.path.join(dir, 'site', 'cicd', 'secrets', 177 passphrase_file_path = os.path.join(_dir, 'site', 'cicd', 'secrets',
159 'passphrases', 178 'passphrases',
160 passphrase_file_name) 179 passphrase_file_name)
161 assert os.path.isfile(passphrase_file_path) 180 assert os.path.isfile(passphrase_file_path)
@@ -200,3 +219,52 @@ def test_generate_passphrases_exception(capture):
200 ('Signature verification to decrypt secrets failed. ' 219 ('Signature verification to decrypt secrets failed. '
201 'Please check your provided passphrase and salt and ' 220 'Please check your provided passphrase and salt and '
202 'try again.'))) 221 'try again.')))
222
223
224@mock.patch.object(
225 util.definition,
226 'documents_for_site',
227 autospec=True,
228 return_value=TEST_GLOBAL_SITE_DOCUMENTS)
229@mock.patch.object(
230 pegleg.config,
231 'get_site_repo',
232 autospec=True,
233 return_value='cicd_site_repo')
234@mock.patch.object(
235 util.definition,
236 'site_files',
237 autospec=True,
238 return_value=[
239 'cicd_global_repo/site/cicd/passphrases/passphrase-catalog.yaml', ])
240@mock.patch.dict(os.environ, {
241 ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
242 ENV_SALT: 'MySecretSalt'})
243def test_global_passphrase_catalog(*_):
244 _dir = tempfile.mkdtemp()
245 os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)
246 PassphraseGenerator('cicd', _dir, 'test_author').generate()
247
248 for passphrase in TEST_GLOBAL_PASSPHRASES_CATALOG['data']['passphrases']:
249 passphrase_file_name = '{}.yaml'.format(passphrase['document_name'])
250 passphrase_file_path = os.path.join(_dir, 'site', 'cicd', 'secrets',
251 'passphrases',
252 passphrase_file_name)
253 assert os.path.isfile(passphrase_file_path)
254 with open(passphrase_file_path) as stream:
255 doc = yaml.safe_load(stream)
256 assert doc['schema'] == 'pegleg/PeglegManagedDocument/v1'
257 assert doc['metadata']['storagePolicy'] == 'cleartext'
258 assert 'encrypted' in doc['data']
259 assert doc['data']['encrypted']['by'] == 'test_author'
260 assert 'generated' in doc['data']
261 assert doc['data']['generated']['by'] == 'test_author'
262 assert 'managedDocument' in doc['data']
263 assert doc['data']['managedDocument']['metadata'][
264 'storagePolicy'] == 'encrypted'
265 decrypted_passphrase = encryption.decrypt(
266 doc['data']['managedDocument']['data'],
267 os.environ['PEGLEG_PASSPHRASE'].encode(),
268 os.environ['PEGLEG_SALT'].encode())
269 if passphrase_file_name == "passphrase_from_global.yaml":
270 assert len(decrypted_passphrase) == 24