Added cleartext option to passphrase generation
Added a force-cleartext option (false by default) which forces passphrases to be generated in cleartext rather than encrypted. Change-Id: I157a40103f67f85a24976b4f59aa46f2d4b92334
This commit is contained in:
parent
820df6d625
commit
52b61b8cfd
@ -874,6 +874,15 @@ are placed in the following folder structure under ``save_location``:
|
||||
|
||||
<save_location>/site/<site_name>/secrets/passphrases/<passphrase_name.yaml>
|
||||
|
||||
**-i / --interactive** (Optional). False by default.
|
||||
|
||||
Generate passphrases interactively, not automatically.
|
||||
|
||||
**--force-cleartext** (Optional). False by default.
|
||||
|
||||
Force cleartext generation of passphrases. This is not
|
||||
recommended.
|
||||
|
||||
Usage:
|
||||
|
||||
::
|
||||
|
@ -106,7 +106,7 @@ ALLOW_MISSING_SUBSTITUTIONS_OPTION = click.option(
|
||||
type=click.BOOL,
|
||||
default=True,
|
||||
show_default=True,
|
||||
help="Raise Deckhand exception on missing substition sources.")
|
||||
help='Raise Deckhand exception on missing substition sources.')
|
||||
|
||||
EXCLUDE_LINT_OPTION = click.option(
|
||||
'-x',
|
||||
@ -131,7 +131,7 @@ SITE_REPOSITORY_ARGUMENT = click.argument(
|
||||
@click.option(
|
||||
'-v',
|
||||
'--verbose',
|
||||
is_flag=bool,
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help='Enable debug logging')
|
||||
def main(*, verbose):
|
||||
@ -235,7 +235,7 @@ def site(*, site_repository, clone_path, extra_repositories, repo_key,
|
||||
help='Directory to output the complete site definition. Created '
|
||||
'automatically if it does not already exist.')
|
||||
@click.option(
|
||||
'--validate',
|
||||
'--validate/--no-validate',
|
||||
'validate',
|
||||
is_flag=True,
|
||||
# TODO(felipemonteiro): Potentially set this to True in the future. This
|
||||
@ -479,7 +479,7 @@ def generate_pki(site_name, author, days):
|
||||
@click.option(
|
||||
'-f',
|
||||
'--filename',
|
||||
'file_name',
|
||||
'filename',
|
||||
help='The relative file path for the file to be wrapped.')
|
||||
@click.option(
|
||||
'-o',
|
||||
@ -512,7 +512,7 @@ def generate_pki(site_name, author, days):
|
||||
show_default=True,
|
||||
help='Whether to encrypt the wrapped file.')
|
||||
@click.argument('site_name')
|
||||
def wrap_secret_cli(*, site_name, author, file_name, output_path, schema,
|
||||
def wrap_secret_cli(*, site_name, author, filename, output_path, schema,
|
||||
name, layer, encrypt):
|
||||
"""Wrap a bare secrets file in a YAML and ManagedDocument.
|
||||
|
||||
@ -520,7 +520,7 @@ def wrap_secret_cli(*, site_name, author, file_name, output_path, schema,
|
||||
|
||||
engine.repository.process_repositories(site_name,
|
||||
overwrite_existing=True)
|
||||
wrap_secret(author, file_name, output_path, schema,
|
||||
wrap_secret(author, filename, output_path, schema,
|
||||
name, layer, encrypt)
|
||||
|
||||
|
||||
@ -652,13 +652,21 @@ def generate():
|
||||
'-i',
|
||||
'--interactive',
|
||||
'interactive',
|
||||
is_flag=bool,
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help='Generate passphrases interactively, not automatically')
|
||||
def generate_passphrases(*, site_name, save_location, author, interactive):
|
||||
@click.option(
|
||||
'--force-cleartext',
|
||||
'force_cleartext',
|
||||
is_flag=True,
|
||||
default=False,
|
||||
show_default=True,
|
||||
help='Force cleartext generation of passphrases. This is not recommended.')
|
||||
def generate_passphrases(*, site_name, save_location, author, interactive,
|
||||
force_cleartext):
|
||||
engine.repository.process_repositories(site_name)
|
||||
engine.secrets.generate_passphrases(site_name, save_location, author,
|
||||
interactive)
|
||||
engine.secrets.generate_passphrases(
|
||||
site_name, save_location, author, interactive, force_cleartext)
|
||||
|
||||
|
||||
@secrets.command(
|
||||
@ -736,7 +744,7 @@ def decrypt(*, path, save_location, overwrite, site_name):
|
||||
os.chmod(file_save_location, 0o600)
|
||||
|
||||
|
||||
@main.group(help="Miscellaneous generate commands")
|
||||
@main.group(help='Miscellaneous generate commands')
|
||||
def generate():
|
||||
pass
|
||||
|
||||
@ -753,7 +761,7 @@ def generate():
|
||||
help='Generate a passphrase of the given length. '
|
||||
'Length is >= 24, no maximum length.')
|
||||
def generate_passphrase(length):
|
||||
click.echo("Generated Passhprase: {}".format(
|
||||
click.echo('Generated Passhprase: {}'.format(
|
||||
engine.secrets.generate_crypto_string(length)))
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@ class PassphraseGenerator(BaseGenerator):
|
||||
self._sitename, documents=self._documents)
|
||||
self._pass_util = CryptoString()
|
||||
|
||||
def generate(self, interactive=False):
|
||||
def generate(self, interactive=False, force_cleartext=False):
|
||||
"""
|
||||
For each passphrase entry in the passphrase catalog, generate a
|
||||
random passphrase string, based on a passphrase specification in the
|
||||
@ -60,6 +60,9 @@ class PassphraseGenerator(BaseGenerator):
|
||||
passphrase document in the pegleg managed document, and encrypt the
|
||||
passphrase. Write the wrapped and encrypted document in a file at
|
||||
<repo_name>/site/<site_name>/secrets/passphrases/passphrase_name.yaml.
|
||||
|
||||
:param bool interactive: If true, run interactively
|
||||
:param bool force_cleartext: If true, don't encrypt
|
||||
"""
|
||||
for p_name in self._catalog.get_passphrase_names:
|
||||
passphrase = None
|
||||
@ -76,7 +79,13 @@ class PassphraseGenerator(BaseGenerator):
|
||||
passphrase = passphrase.encode()
|
||||
passphrase = base64.b64encode(passphrase)
|
||||
docs = list()
|
||||
if force_cleartext:
|
||||
storage_policy = passphrase_catalog.P_CLEARTEXT
|
||||
LOG.warning("Passphrases for {} will be "
|
||||
"generated in clear text.".format(p_name))
|
||||
else:
|
||||
storage_policy = self._catalog.get_storage_policy(p_name)
|
||||
|
||||
docs.append(self.generate_doc(
|
||||
KIND,
|
||||
p_name,
|
||||
|
@ -131,21 +131,24 @@ def _get_dest_path(repo_base, file_path, save_location):
|
||||
return file_path
|
||||
|
||||
|
||||
def generate_passphrases(site_name, save_location, author, interactive=False):
|
||||
def generate_passphrases(site_name, save_location, author, interactive=False,
|
||||
force_cleartext=False):
|
||||
"""
|
||||
Look for the site passphrase catalogs, and for every passphrase entry in
|
||||
the passphrase catalog generate a passphrase document, wrap the
|
||||
passphrase document in a pegleg managed document, and encrypt the
|
||||
passphrase data.
|
||||
|
||||
:param interactive: Whether to generate the results interactively
|
||||
:param str site_name: The site to read from
|
||||
:param str save_location: Location to write files to
|
||||
:param str author:
|
||||
:param str author: Author who's generating the files
|
||||
:param bool interactive: Whether to generate the results interactively
|
||||
:param bool force_cleartext: Whether to generate results in clear text
|
||||
"""
|
||||
|
||||
PassphraseGenerator(site_name, save_location, author).generate(
|
||||
interactive=interactive)
|
||||
PassphraseGenerator(
|
||||
site_name, save_location, author).generate(
|
||||
interactive=interactive, force_cleartext=force_cleartext)
|
||||
|
||||
|
||||
def generate_crypto_string(length):
|
||||
@ -159,12 +162,12 @@ def generate_crypto_string(length):
|
||||
return CryptoString().get_crypto_string(length)
|
||||
|
||||
|
||||
def wrap_secret(author, file_name, output_path, schema,
|
||||
def wrap_secret(author, filename, output_path, schema,
|
||||
name, layer, encrypt):
|
||||
"""Wrap a bare secrets file in a YAML and ManagedDocument.
|
||||
|
||||
:param author: author for ManagedDocument
|
||||
:param file_name: file path for input file
|
||||
:param filename: file path for input file
|
||||
:param output_path: file path for output file
|
||||
:param schema: schema for wrapped document
|
||||
:param name: name for wrapped document
|
||||
@ -173,9 +176,9 @@ def wrap_secret(author, file_name, output_path, schema,
|
||||
"""
|
||||
|
||||
if not output_path:
|
||||
output_path = os.path.splitext(file_name)[0] + ".yaml"
|
||||
output_path = os.path.splitext(filename)[0] + ".yaml"
|
||||
|
||||
with open(file_name, "r") as in_fi:
|
||||
with open(filename, "r") as in_fi:
|
||||
data = in_fi.read()
|
||||
|
||||
inner_doc = {
|
||||
|
@ -75,7 +75,7 @@ def site_files(site_name):
|
||||
|
||||
|
||||
def site_files_by_repo(site_name):
|
||||
"""Yield tuples of repo_base, file_name."""
|
||||
"""Yield tuples of repo_base, filename."""
|
||||
params = load_as_params(site_name)
|
||||
dir_map = files.directories_for_each_repo(**params)
|
||||
for repo, dl in dir_map.items():
|
||||
|
@ -411,7 +411,7 @@ def file_in_subdir(filename, _dir):
|
||||
:return: Whether _dir is a parent of the file
|
||||
:rtype: bool
|
||||
"""
|
||||
file_path, file_name = os.path.split(
|
||||
file_path, filename = os.path.split(
|
||||
os.path.realpath(filename))
|
||||
return _dir in file_path.split(os.path.sep)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user