pegleg/tests/unit/fixtures.py
Felipe Monteiro 2a8d2638b3 pki: Port Promenade's PKI catalog into Pegleg
This patch set implements the PKICatalog [0] requirements
as well as PeglegManagedDocument [1] generation requirements
outlined in the spec [2].

Included in this patch set:

* New CLI entry point called "pegleg site secrets generate-pki"
* PeglegManagedDocument generation logic in
  engine.cache.managed_document
* Refactored PKICatalog logic in engine.cache.pki_catalog derived
  from the Promenade PKI implementation [3], responsible for
  generating certificates, CAs, and keypairs
* Refactored PKIGenerator logic in engine.cache.pki_generator
  derived from Promenade Generator implementation [4],
  responsible for reading in pegleg/PKICatalog/v1 documents (as
  well as promenade/PKICatalog/v1 documents for backwards
  compatibility) and generating required secrets and storing
  them into the paths specified under [0]
* Unit tests for all of the above [5]
* Example pki-catalog.yaml document under pegleg/site_yamls
* Validation schema for pki-catalog.yaml (TODO: implement
  validation logic here: [6])
* Updates to CLI documentation and inclusion of PKICatalog
  and PeglegManagedDocument documentation
* Documentation updates with PKI information [7]

TODO (in follow-up patch sets):

* Expand on overview documentation to include new Pegleg
  responsibilities
* Allow the original repository (not the copied one) to
  be the destination where the secrets are written to
* Finish up cert expiry/revocation logic

[0] https://airship-specs.readthedocs.io/en/latest/specs/approved/pegleg-secrets.html#document-generation
[1] https://airship-specs.readthedocs.io/en/latest/specs/approved/pegleg-secrets.html#peglegmanageddocument
[2] https://airship-specs.readthedocs.io/en/latest/specs/approved/pegleg-secrets.html
[3] https://github.com/openstack/airship-promenade/blob/master/promenade/pki.py
[4] https://github.com/openstack/airship-promenade/blob/master/promenade/generator.py
[5] https://review.openstack.org/#/c/611739/
[6] https://review.openstack.org/#/c/608159/
[7] https://review.openstack.org/#/c/611738/

Change-Id: I3010d04cac6d22c656d144f0dafeaa5e19a13068
2019-01-15 13:29:21 -06:00

170 lines
4.8 KiB
Python

# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
import copy
import os
import shutil
import tempfile
import pytest
import yaml
from pegleg import config
from pegleg.engine.util import files
TEST_DOCUMENT = """
---
schema: deckhand/Passphrase/v1
metadata:
schema: metadata/Document/v1
name: %(name)s
storagePolicy: %(storagePolicy)s
layeringDefinition:
abstract: False
layer: %(layer)s
data: %(name)s-password
...
"""
def _gen_document(**kwargs):
if "storagePolicy" not in kwargs:
kwargs["storagePolicy"] = "cleartext"
test_document = TEST_DOCUMENT % kwargs
return yaml.load(test_document)
@pytest.fixture()
def create_tmp_deployment_files(tmpdir):
"""Fixture that creates a temporary directory structure."""
sitenames = ['cicd', 'lab']
SITE_TEST_STRUCTURE = {
'directories': {
'secrets': {
'directories': {
'passphrases': {
'files': {}
},
},
},
'software': {
'directories': {
'charts': {
'files': {}
},
},
},
},
'files': {}
}
p = tmpdir.mkdir("deployment_files")
config.set_site_repo(str(p))
# Create global directories and files.
files._create_tree(
os.path.join(str(p), 'global'),
tree={
'directories': {
'common': {
'files': {
'global-common.yaml':
_gen_document(name="global-common", layer='global')
}
},
'v1.0': {
'files': {
'global-v1.0.yaml':
_gen_document(name="global-v1.0", layer='global')
}
}
}
})
# Create type directories and files.
files._create_tree(
os.path.join(str(p), 'type'),
tree={
'directories': {
site: {
'directories': {
'common': {
'files': {
'%s-type-common.yaml' % site:
_gen_document(
name="%s-type-common" % site, layer='type')
}
},
'v1.0': {
'files': {
'%s-type-v1.0.yaml' % site:
_gen_document(
name="%s-type-v1.0" % site, layer='type')
}
}
}
}
for site in sitenames
}
})
# Create site directories and files.
for site in sitenames:
site_definition = """
---
data:
repositories:
global:
revision: v1.0
url: http://nothing.com
site_type: %s
metadata:
layeringDefinition: {abstract: false, layer: site}
name: %s
schema: metadata/Document/v1
storagePolicy: cleartext
schema: pegleg/SiteDefinition/v1
""" % (site, site)
test_structure = SITE_TEST_STRUCTURE.copy()
test_structure['directories']['secrets']['directories']['passphrases'][
'files'] = {
'%s-passphrase.yaml' % site:
_gen_document(name="%s-passphrase" % site, layer='site')
}
test_structure['directories']['software']['directories']['charts'][
'files'] = {
'%s-chart.yaml' % site:
_gen_document(name="%s-chart" % site, layer='site')
}
test_structure['files']['site-definition.yaml'] = yaml.safe_load(
site_definition)
cicd_path = os.path.join(str(p), files._site_path(site))
files._create_tree(cicd_path, tree=test_structure)
yield tmpdir
@pytest.fixture()
def temp_path():
temp_folder = tempfile.mkdtemp()
try:
yield temp_folder
finally:
if os.path.exists(temp_folder):
shutil.rmtree(temp_folder, ignore_errors=True)