Merge "Set salt when generating genesis bundle"
This commit is contained in:
commit
bc0e420bc4
Binary file not shown.
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
@ -434,26 +434,15 @@ def generate_pki(site_name, author):
|
||||||
'to genesis.sh script.')
|
'to genesis.sh script.')
|
||||||
@SITE_REPOSITORY_ARGUMENT
|
@SITE_REPOSITORY_ARGUMENT
|
||||||
def genesis_bundle(*, build_dir, validators, site_name):
|
def genesis_bundle(*, build_dir, validators, site_name):
|
||||||
prom_encryption_key = os.environ.get("PROMENADE_ENCRYPTION_KEY")
|
passphrase = os.environ.get("PEGLEG_PASSPHRASE")
|
||||||
peg_encryption_key = os.environ.get("PEGLEG_PASSPHRASE")
|
salt = os.environ.get("PEGLEG_SALT")
|
||||||
encryption_key = None
|
encryption_key = passphrase
|
||||||
if (prom_encryption_key and len(prom_encryption_key) > 24 and
|
if passphrase:
|
||||||
peg_encryption_key and len(peg_encryption_key) > 24):
|
passphrase = passphrase.encode()
|
||||||
click.echo("WARNING: PROMENADE_ENCRYPTION_KEY is deprecated, "
|
if salt:
|
||||||
"using PEGLEG_PASSPHRASE instead", err=True)
|
salt = salt.encode()
|
||||||
config.set_passphrase(peg_encryption_key)
|
config.set_passphrase(passphrase)
|
||||||
encryption_key = peg_encryption_key
|
config.set_salt(salt)
|
||||||
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.")
|
|
||||||
|
|
||||||
PeglegSecretManagement.check_environment()
|
PeglegSecretManagement.check_environment()
|
||||||
bundle.build_genesis(build_dir,
|
bundle.build_genesis(build_dir,
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
# context passing but will require a somewhat heavy code refactor. See:
|
# context passing but will require a somewhat heavy code refactor. See:
|
||||||
# http://click.pocoo.org/5/commands/#nested-handling-and-contexts
|
# http://click.pocoo.org/5/commands/#nested-handling-and-contexts
|
||||||
|
|
||||||
|
from pegleg.engine import exceptions
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if GLOBAL_CONTEXT:
|
if GLOBAL_CONTEXT:
|
||||||
pass
|
pass
|
||||||
|
@ -28,7 +30,9 @@ except NameError:
|
||||||
'site_rev': None,
|
'site_rev': None,
|
||||||
'type_path': 'type',
|
'type_path': 'type',
|
||||||
'passphrase': None,
|
'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
|
GLOBAL_CONTEXT['type_path'] = p
|
||||||
|
|
||||||
|
|
||||||
def set_passphrase(p):
|
def set_passphrase(passphrase):
|
||||||
"""Set the passphrase for encryption and decryption."""
|
"""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():
|
def get_passphrase():
|
||||||
|
@ -161,9 +171,15 @@ def get_passphrase():
|
||||||
return GLOBAL_CONTEXT['passphrase']
|
return GLOBAL_CONTEXT['passphrase']
|
||||||
|
|
||||||
|
|
||||||
def set_salt(p):
|
def set_salt(salt):
|
||||||
"""Set the salt for encryption and decryption."""
|
"""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():
|
def get_salt():
|
||||||
|
|
|
@ -102,3 +102,31 @@ class GenesisBundleGenerateException(PeglegBaseException):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message = 'Bundle generation failed on deckhand validation.'
|
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.'
|
||||||
|
|
|
@ -91,7 +91,7 @@ data: ABAgagajajkb839215387
|
||||||
|
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_no_encryption_key(temp_path):
|
def test_no_encryption_key(temp_path):
|
||||||
# Write the test data to temp file
|
# Write the test data to temp file
|
||||||
|
@ -119,7 +119,7 @@ def test_no_encryption_key(temp_path):
|
||||||
|
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_failed_deckhand_validation(temp_path):
|
def test_failed_deckhand_validation(temp_path):
|
||||||
# Write the test data to temp file
|
# Write the test data to temp file
|
||||||
|
|
|
@ -166,7 +166,7 @@ def test_cryptostring_long_len():
|
||||||
'cicd_site_repo/site/cicd/passphrases/passphrase-catalog.yaml', ])
|
'cicd_site_repo/site/cicd/passphrases/passphrase-catalog.yaml', ])
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'})
|
ENV_SALT: 'MySecretSalt1234567890]['})
|
||||||
def test_generate_passphrases(*_):
|
def test_generate_passphrases(*_):
|
||||||
_dir = tempfile.mkdtemp()
|
_dir = tempfile.mkdtemp()
|
||||||
os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)
|
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', ])
|
'cicd_global_repo/site/cicd/passphrases/passphrase-catalog.yaml', ])
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'})
|
ENV_SALT: 'MySecretSalt1234567890]['})
|
||||||
def test_global_passphrase_catalog(*_):
|
def test_global_passphrase_catalog(*_):
|
||||||
_dir = tempfile.mkdtemp()
|
_dir = tempfile.mkdtemp()
|
||||||
os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)
|
os.makedirs(os.path.join(_dir, 'cicd_site_repo'), exist_ok=True)
|
||||||
|
|
|
@ -74,7 +74,7 @@ def test_encrypt_and_decrypt():
|
||||||
|
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'aShortPassphrase',
|
ENV_PASSPHRASE: 'aShortPassphrase',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_short_passphrase():
|
def test_short_passphrase():
|
||||||
with pytest.raises(click.ClickException,
|
with pytest.raises(click.ClickException,
|
||||||
|
@ -84,7 +84,7 @@ def test_short_passphrase():
|
||||||
|
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'})
|
ENV_SALT: 'MySecretSalt1234567890]['})
|
||||||
def test_secret_encrypt_and_decrypt(create_tmp_deployment_files, tmpdir):
|
def test_secret_encrypt_and_decrypt(create_tmp_deployment_files, tmpdir):
|
||||||
site_dir = tmpdir.join("deployment_files", "site", "cicd")
|
site_dir = tmpdir.join("deployment_files", "site", "cicd")
|
||||||
passphrase_doc = """---
|
passphrase_doc = """---
|
||||||
|
@ -160,7 +160,7 @@ def test_pegleg_secret_management_constructor_with_invalid_arguments():
|
||||||
|
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_encrypt_decrypt_using_file_path(temp_path):
|
def test_encrypt_decrypt_using_file_path(temp_path):
|
||||||
# write the test data to temp file
|
# 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, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_encrypt_decrypt_using_docs(temp_path):
|
def test_encrypt_decrypt_using_docs(temp_path):
|
||||||
# write the test data to temp file
|
# 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')
|
reason='cfssl must be installed to execute these tests')
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_generate_pki_using_local_repo_path(create_tmp_deployment_files):
|
def test_generate_pki_using_local_repo_path(create_tmp_deployment_files):
|
||||||
"""Validates ``generate-pki`` action using local repo path."""
|
"""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')
|
reason='cfssl must be installed to execute these tests')
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
ENV_SALT: 'MySecretSalt'
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
})
|
})
|
||||||
def test_check_expiry(create_tmp_deployment_files):
|
def test_check_expiry(create_tmp_deployment_files):
|
||||||
""" Validates check_expiry """
|
""" Validates check_expiry """
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import mock
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -20,6 +22,8 @@ from tests.unit import test_utils
|
||||||
from mock import ANY
|
from mock import ANY
|
||||||
|
|
||||||
from pegleg.engine import util
|
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 ShipyardHelper
|
||||||
from pegleg.engine.util.shipyard_helper import ShipyardClient
|
from pegleg.engine.util.shipyard_helper import ShipyardClient
|
||||||
|
|
||||||
|
@ -102,6 +106,10 @@ def test_shipyard_helper_init_():
|
||||||
return_value=DATA)
|
return_value=DATA)
|
||||||
@mock.patch.object(ShipyardHelper, 'formatted_response_handler',
|
@mock.patch.object(ShipyardHelper, 'formatted_response_handler',
|
||||||
autospec=True, return_value=None)
|
autospec=True, return_value=None)
|
||||||
|
@mock.patch.dict(os.environ, {
|
||||||
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
|
})
|
||||||
def test_upload_documents(*args):
|
def test_upload_documents(*args):
|
||||||
""" Tests upload document """
|
""" Tests upload document """
|
||||||
# Scenario:
|
# Scenario:
|
||||||
|
@ -128,6 +136,10 @@ def test_upload_documents(*args):
|
||||||
return_value=DATA)
|
return_value=DATA)
|
||||||
@mock.patch.object(ShipyardHelper, 'formatted_response_handler',
|
@mock.patch.object(ShipyardHelper, 'formatted_response_handler',
|
||||||
autospec=True, return_value=None)
|
autospec=True, return_value=None)
|
||||||
|
@mock.patch.dict(os.environ, {
|
||||||
|
ENV_PASSPHRASE: 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
|
ENV_SALT: 'MySecretSalt1234567890]['
|
||||||
|
})
|
||||||
def test_upload_documents_fail(*args):
|
def test_upload_documents_fail(*args):
|
||||||
""" Tests Document upload error """
|
""" Tests Document upload error """
|
||||||
# Scenario:
|
# Scenario:
|
||||||
|
|
|
@ -459,7 +459,7 @@ class TestSiteSecretsActions(BaseCLIActionTest):
|
||||||
super(TestSiteSecretsActions, cls).setup_class()
|
super(TestSiteSecretsActions, cls).setup_class()
|
||||||
cls.runner = CliRunner(env={
|
cls.runner = CliRunner(env={
|
||||||
"PEGLEG_PASSPHRASE": 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
"PEGLEG_PASSPHRASE": 'ytrr89erARAiPE34692iwUMvWqqBvC',
|
||||||
"PEGLEG_SALT": "MySecretSalt"
|
"PEGLEG_SALT": "MySecretSalt1234567890]["
|
||||||
})
|
})
|
||||||
|
|
||||||
def _validate_generate_pki_action(self, result):
|
def _validate_generate_pki_action(self, result):
|
||||||
|
@ -514,7 +514,7 @@ class TestSiteSecretsActions(BaseCLIActionTest):
|
||||||
reason='cfssl must be installed to execute these tests')
|
reason='cfssl must be installed to execute these tests')
|
||||||
@mock.patch.dict(os.environ, {
|
@mock.patch.dict(os.environ, {
|
||||||
"PEGLEG_PASSPHRASE": "123456789012345678901234567890",
|
"PEGLEG_PASSPHRASE": "123456789012345678901234567890",
|
||||||
"PEGLEG_SALT": "123456"
|
"PEGLEG_SALT": "MySecretSalt1234567890]["
|
||||||
})
|
})
|
||||||
def test_site_secrets_encrypt_and_decrypt_local_repo_path(self):
|
def test_site_secrets_encrypt_and_decrypt_local_repo_path(self):
|
||||||
"""Validates ``generate-pki`` action using local repo path."""
|
"""Validates ``generate-pki`` action using local repo path."""
|
||||||
|
|
Loading…
Reference in New Issue