Set salt when generating genesis bundle

This patch:
1. Sets the salt in config when running genesis bundle
2. Updates the genesis bundle CLI method
3. Adds exception types for credentials
4. Updates unit tests to be compliant with new exceptions

Change-Id: I8869f897e2c25b98c30eaa6be52356aae4ac63b6
This commit is contained in:
Alexander Hughes 2019-03-12 13:21:31 -05:00
parent c4f25b4d4f
commit fce12add18
9 changed files with 82 additions and 37 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -434,26 +434,15 @@ def generate_pki(site_name, author):
'to genesis.sh script.')
@SITE_REPOSITORY_ARGUMENT
def genesis_bundle(*, build_dir, validators, site_name):
prom_encryption_key = os.environ.get("PROMENADE_ENCRYPTION_KEY")
peg_encryption_key = os.environ.get("PEGLEG_PASSPHRASE")
encryption_key = None
if (prom_encryption_key and len(prom_encryption_key) > 24 and
peg_encryption_key and len(peg_encryption_key) > 24):
click.echo("WARNING: PROMENADE_ENCRYPTION_KEY is deprecated, "
"using PEGLEG_PASSPHRASE instead", err=True)
config.set_passphrase(peg_encryption_key)
encryption_key = peg_encryption_key
elif prom_encryption_key and len(prom_encryption_key) > 24:
click.echo("ERROR: PROMENADE_ENCRYPTION_KEY is deprecated, "
"use PEGLEG_PASSPHRASE instead", err=True)
raise click.ClickException("ERROR: PEGLEG_PASSPHRASE must be set "
"and at least 24 characters long.")
elif peg_encryption_key and len(peg_encryption_key) > 24:
config.set_passphrase(peg_encryption_key)
encryption_key = peg_encryption_key
else:
raise click.ClickException("ERROR: PEGLEG_PASSPHRASE must be set "
"and at least 24 characters long.")
passphrase = os.environ.get("PEGLEG_PASSPHRASE")
salt = os.environ.get("PEGLEG_SALT")
encryption_key = passphrase
if passphrase:
passphrase = passphrase.encode()
if salt:
salt = salt.encode()
config.set_passphrase(passphrase)
config.set_salt(salt)
PeglegSecretManagement.check_environment()
bundle.build_genesis(build_dir,

View File

@ -16,6 +16,8 @@
# context passing but will require a somewhat heavy code refactor. See:
# http://click.pocoo.org/5/commands/#nested-handling-and-contexts
from pegleg.engine import exceptions
try:
if GLOBAL_CONTEXT:
pass
@ -28,7 +30,9 @@ except NameError:
'site_rev': None,
'type_path': 'type',
'passphrase': None,
'salt': None
'salt': None,
'salt_min_length': 24,
'passphrase_min_length': 24
}
@ -151,9 +155,15 @@ def set_rel_type_path(p):
GLOBAL_CONTEXT['type_path'] = p
def set_passphrase(p):
def set_passphrase(passphrase):
"""Set the passphrase for encryption and decryption."""
GLOBAL_CONTEXT['passphrase'] = p
if not passphrase:
raise exceptions.PassphraseNotFoundException()
elif len(passphrase) < GLOBAL_CONTEXT['passphrase_min_length']:
raise exceptions.PassphraseInsufficientLengthException()
GLOBAL_CONTEXT['passphrase'] = passphrase
def get_passphrase():
@ -161,9 +171,15 @@ def get_passphrase():
return GLOBAL_CONTEXT['passphrase']
def set_salt(p):
def set_salt(salt):
"""Set the salt for encryption and decryption."""
GLOBAL_CONTEXT['salt'] = p
if not salt:
raise exceptions.SaltNotFoundException()
elif len(salt) < GLOBAL_CONTEXT['salt_min_length']:
raise exceptions.SaltInsufficientLengthException()
GLOBAL_CONTEXT['salt'] = salt
def get_salt():

View File

@ -102,3 +102,31 @@ class GenesisBundleGenerateException(PeglegBaseException):
"""
message = 'Bundle generation failed on deckhand validation.'
#
# CREDENTIALS EXCEPTIONS
#
class PassphraseNotFoundException(PeglegBaseException):
"""Exception raised when passphrase is not set."""
message = 'PEGLEG_PASSPHRASE must be set'
class PassphraseInsufficientLengthException(PeglegBaseException):
"""Exception raised when passphrase is too short."""
message = 'PEGLEG_PASSPHRASE must be at least 24 characters long.'
class SaltNotFoundException(PeglegBaseException):
"""Exception raised when salt is not set."""
message = 'PEGLEG_SALT must be set'
class SaltInsufficientLengthException(PeglegBaseException):
"""Exception raised when salt is too short."""
message = 'PEGLEG_SALT must be at least 24 characters long.'

View File

@ -91,7 +91,7 @@ data: ABAgagajajkb839215387
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_no_encryption_key(temp_path):
# Write the test data to temp file
@ -119,7 +119,7 @@ def test_no_encryption_key(temp_path):
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_failed_deckhand_validation(temp_path):
# Write the test data to temp file

View File

@ -166,7 +166,7 @@ def test_cryptostring_long_len():
'cicd_site_repo/site/cicd/passphrases/passphrase-catalog.yaml', ])
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'})
ENV_SALT: 'MySecretSalt1234567890]['})
def test_generate_passphrases(*_):
_dir = tempfile.mkdtemp()
os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)
@ -239,7 +239,7 @@ def test_generate_passphrases_exception(capture):
'cicd_global_repo/site/cicd/passphrases/passphrase-catalog.yaml', ])
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'})
ENV_SALT: 'MySecretSalt1234567890]['})
def test_global_passphrase_catalog(*_):
_dir = tempfile.mkdtemp()
os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)

View File

@ -74,7 +74,7 @@ def test_encrypt_and_decrypt():
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'aShortPassphrase',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_short_passphrase():
with pytest.raises(click.ClickException,
@ -84,7 +84,7 @@ def test_short_passphrase():
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'})
ENV_SALT: 'MySecretSalt1234567890]['})
def test_secret_encrypt_and_decrypt(create_tmp_deployment_files, tmpdir):
site_dir = tmpdir.join("deployment_files", "site", "cicd")
passphrase_doc = """---
@ -160,7 +160,7 @@ def test_pegleg_secret_management_constructor_with_invalid_arguments():
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_encrypt_decrypt_using_file_path(temp_path):
# write the test data to temp file
@ -190,7 +190,7 @@ def test_encrypt_decrypt_using_file_path(temp_path):
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_encrypt_decrypt_using_docs(temp_path):
# write the test data to temp file
@ -226,7 +226,7 @@ def test_encrypt_decrypt_using_docs(temp_path):
reason='cfssl must be installed to execute these tests')
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_generate_pki_using_local_repo_path(create_tmp_deployment_files):
"""Validates ``generate-pki`` action using local repo path."""
@ -252,7 +252,7 @@ def test_generate_pki_using_local_repo_path(create_tmp_deployment_files):
reason='cfssl must be installed to execute these tests')
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt'
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_check_expiry(create_tmp_deployment_files):
""" Validates check_expiry """

View File

@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import json
import mock
import pytest
@ -20,6 +22,8 @@ from tests.unit import test_utils
from mock import ANY
from pegleg.engine import util
from pegleg.engine.util.pegleg_secret_management import ENV_PASSPHRASE
from pegleg.engine.util.pegleg_secret_management import ENV_SALT
from pegleg.engine.util.shipyard_helper import ShipyardHelper
from pegleg.engine.util.shipyard_helper import ShipyardClient
@ -89,6 +93,10 @@ def test_shipyard_helper_init_():
return_value=DATA)
@mock.patch.object(ShipyardHelper, 'formatted_response_handler',
autospec=True, return_value=None)
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_upload_documents(*args):
""" Tests upload document """
# Scenario:
@ -115,6 +123,10 @@ def test_upload_documents(*args):
return_value=DATA)
@mock.patch.object(ShipyardHelper, 'formatted_response_handler',
autospec=True, return_value=None)
@mock.patch.dict(os.environ, {
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
ENV_SALT: 'MySecretSalt1234567890]['
})
def test_upload_documents_fail(*args):
""" Tests Document upload error """
# Scenario:

View File

@ -459,7 +459,7 @@ class TestSiteSecretsActions(BaseCLIActionTest):
super(TestSiteSecretsActions, cls).setup_class()
cls.runner = CliRunner(env={
"PEGLEG_PASSPHRASE": 'ytrr89erARAiPE34692iwUMvWqqBvC',
"PEGLEG_SALT": "MySecretSalt"
"PEGLEG_SALT": "MySecretSalt1234567890]["
})
def _validate_generate_pki_action(self, result):
@ -514,7 +514,7 @@ class TestSiteSecretsActions(BaseCLIActionTest):
reason='cfssl must be installed to execute these tests')
@mock.patch.dict(os.environ, {
"PEGLEG_PASSPHRASE": "123456789012345678901234567890",
"PEGLEG_SALT": "123456"
"PEGLEG_SALT": "MySecretSalt1234567890]["
})
def test_site_secrets_encrypt_and_decrypt_local_repo_path(self):
"""Validates ``generate-pki`` action using local repo path."""