Exemplo n.º 1
0
def run_decrypt(overwrite, path, save_location, site_name):
    """Unwraps and decrypts secret documents for a site

    :param overwrite: if True, overwrites original files with decrypted
    :param path: file(s) or directory(ies) to decrypt
    :param save_location: if specified saves to the given path, otherwise
                          returns list of decrypted information
    :param site_name: site name to process
    :return: decrypted data list if save_location is None
    :rtype: list
    """
    decrypted_data = []
    config.set_global_enc_keys(site_name)
    if type(path) is not list and type(path) is not tuple:
        path = [path]
    for p in path:
        decrypted = engine.secrets.decrypt(p, site_name=site_name)
        if overwrite:
            for file_path, data in decrypted.items():
                files.write(data, file_path)
        elif save_location is None:
            for data in decrypted.values():
                decrypted_data.append(data)
        else:
            for file_path, data in decrypted.items():
                file_name = os.path.split(file_path)[1]
                file_save_location = os.path.join(save_location, file_name)
                files.write(data, file_save_location)
    return decrypted_data
Exemplo n.º 2
0
def list_types(output_stream):
    """List type names for a given repository."""

    # Create a table to output site types for a given repo
    type_table = PrettyTable()
    type_table.field_names = ['type_name']
    for type_name in util.files.list_types():
        type_table.add_row([type_name])
    # Write table to specified output_stream
    msg = type_table.get_string()
    if output_stream:
        files.write(msg + "\n", output_stream)
    else:
        click.echo(msg)
Exemplo n.º 3
0
def list_(output_stream):
    """List site names for a given repository."""

    # Create a table to output site information for all sites for a given repo
    site_table = PrettyTable()
    field_names = ['site_name', 'site_type']
    site_table.field_names = field_names

    for site_name in util.files.list_sites():
        params = util.definition.load_as_params(site_name, *field_names)
        site_table.add_row(list(map(lambda k: params[k], field_names)))
    # Write table to specified output_stream
    msg = site_table.get_string()
    if output_stream:
        files.write(msg + "\n", output_stream)
    else:
        click.echo(msg)
Exemplo n.º 4
0
def show(site_name, output_stream):
    data = util.definition.load_as_params(site_name)
    data['files'] = list(util.definition.site_files(site_name))
    # Create a table to output site information for specific site
    site_table = PrettyTable()
    site_table.field_names = ['revision', 'site_name', 'site_type', 'files']
    # TODO(felipemonteiro): Drop support for 'revision' once manifest
    # repositories have removed it altogether.
    if 'revision' in data.keys():
        for file in data['files']:
            site_table.add_row(
                [data['revision'], data['site_name'], data['site_type'], file])
    else:
        for file in data['files']:
            site_table.add_row(
                ["", data['site_name'], data['site_type'], file])
    # Write tables to specified output_stream
    msg = site_table.get_string()
    if output_stream:
        files.write(msg + "\n", output_stream)
    else:
        click.echo(msg)
Exemplo n.º 5
0
def test_encrypt_decrypt_using_file_path(tmpdir):
    # write the test data to temp file
    test_data = list(yaml.safe_load_all(TEST_DATA))
    file_path = os.path.join(tmpdir, 'secrets_file.yaml')
    files.write(test_data, file_path)
    save_path = os.path.join(tmpdir, 'encrypted_secrets_file.yaml')

    # encrypt documents and validate that they were encrypted
    doc_mgr = PeglegSecretManagement(file_path=file_path, author='test_author')
    doc_mgr.encrypt_secrets(save_path)
    doc = doc_mgr.documents[0]
    assert doc.is_encrypted()
    assert doc.data['encrypted']['by'] == 'test_author'

    # decrypt documents and validate that they were decrypted
    doc_mgr = PeglegSecretManagement(file_path=file_path, author='test_author')
    doc_mgr.encrypt_secrets(save_path)
    # read back the encrypted file
    doc_mgr = PeglegSecretManagement(file_path=save_path, author='test_author')
    decrypted_data = doc_mgr.get_decrypted_secrets()
    assert test_data[0]['data'] == decrypted_data[0]['data']
    assert test_data[0]['schema'] == decrypted_data[0]['schema']
Exemplo n.º 6
0
def test_failed_deckhand_validation(tmpdir):
    # Write the test data to temp file
    config_data = list(yaml.safe_load_all(SITE_CONFIG_DATA))
    base_config_dir = os.path.join(tmpdir, 'config_dir')
    config.set_site_repo(base_config_dir)
    config_dir = os.path.join(base_config_dir, 'site', 'test_site')

    config_path = os.path.join(config_dir, 'config_file.yaml')
    build_dir = os.path.join(tmpdir, 'build_dir')
    os.makedirs(config_dir)
    files.write(config_data, config_path)
    files.write(
        yaml.safe_load_all(SITE_DEFINITION),
        os.path.join(config_dir, "site-definition.yaml"))
    key = 'MyverYSecretEncryptionKey382803'
    with pytest.raises(GenesisBundleGenerateException,
                       match=r'.*failed on deckhand validation.*'):
        bundle.build_genesis(
            build_path=build_dir,
            encryption_key=key,
            validators=False,
            debug=logging.ERROR,
            site_name="test_site")
Exemplo n.º 7
0
    def encrypt_secrets(self, save_path):
        """
        Wrap and encrypt the secrets documents included in the input file,
        into pegleg manage secrets documents, and write the result in
        save_path.

        if save_path is the same as the source file_path the encrypted file
        will overwrite the source file.

        :param save_path: Destination path of the encrypted file
        :type save_path: string
        :param author: Identifier for the program or person who is
        encrypting the secrets documents
        :type author: string
        """

        doc_list, encrypted_docs = self.get_encrypted_secrets()
        if encrypted_docs:
            files.write(doc_list, save_path)
            click.echo('Wrote encrypted data to: {}'.format(save_path))
        else:
            LOG.debug('All documents in file: {} are either already encrypted '
                      'or have cleartext storage policy. '
                      'Skipping.'.format(self.file_path))
Exemplo n.º 8
0
    def test_write(self, temp_deployment_files):
        path = os.path.join(config.get_site_repo(), 'site', 'cicd',
                            'test_out.yaml')
        files.write("test text", path)
        with open(path, "r") as out_fi:
            assert out_fi.read() == "test text"

        files.write({"a": 1}, path)
        with open(path, "r") as out_fi:
            assert yaml.safe_load(out_fi) == {"a": 1}

        files.write([{"a": 1}], path)
        with open(path, "r") as out_fi:
            assert list(yaml.safe_load_all(out_fi)) == [{"a": 1}]

        with pytest.raises(ValueError):
            files.write(object(), path)
Exemplo n.º 9
0
def test_no_encryption_key(tmpdir):
    # Write the test data to temp file
    config_data = list(yaml.safe_load_all(SITE_CONFIG_DATA))
    base_config_dir = os.path.join(tmpdir, 'config_dir')
    config.set_site_repo(base_config_dir)
    config_dir = os.path.join(base_config_dir, 'site', 'test_site')

    config_path = os.path.join(config_dir, 'config_file.yaml')
    build_dir = os.path.join(tmpdir, 'build_dir')
    os.makedirs(config_dir)

    files.write(config_data, config_path)
    files.write(
        yaml.safe_load_all(SITE_DEFINITION),
        os.path.join(config_dir, "site-definition.yaml"))

    with pytest.raises(GenesisBundleEncryptionException,
                       match=r'.*no encryption policy or key is specified.*'):
        bundle.build_genesis(
            build_path=build_dir,
            encryption_key=None,
            validators=False,
            debug=logging.ERROR,
            site_name="test_site")
Exemplo n.º 10
0
 def test_file_permissions(self, temp_deployment_files):
     path = os.path.join(config.get_site_repo(), 'site', 'cicd',
                         'test_out.yaml')
     files.write("test text", path)
     assert oct(os.stat(path).st_mode & 0o777) == EXPECTED_FILE_PERM
Exemplo n.º 11
0
    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
        catalog. Create a pegleg managed document, wrap the generated
        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, allow input
        :param bool force_cleartext: If true, don't encrypt
        """
        for p_name in self._catalog.get_passphrase_names:
            # Check if this secret is present and should not be regenerated
            save_path = self.get_save_path(p_name)
            regenerable = self._catalog.is_passphrase_regenerable(p_name)
            if os.path.exists(save_path) and not regenerable:
                continue

            # Generate secret as it either does not exist yet or is a
            # regenerable secret and does exist but should be rotated.
            passphrase = None
            passphrase_type = self._catalog.get_passphrase_type(p_name)
            prompt = self._catalog.is_passphrase_prompt(p_name)
            profile = self._catalog.get_passphrase_profile(p_name)
            if interactive and prompt:
                auto_allowed = regenerable

                if passphrase_type == 'uuid':  # nosec
                    passphrase = self._prompt_user_passphrase_and_validate(
                        p_name,
                        'UUID',
                        self.validate_uuid,
                        auto_allowed=auto_allowed)

                elif passphrase_type == 'base64':  # nosec
                    passphrase = self._prompt_user_passphrase_and_validate(
                        p_name,
                        'passphrase (b64)',
                        self.validate_base64,
                        auto_allowed=auto_allowed)

                elif passphrase_type == 'passphrase':
                    passphrase = self._prompt_user_passphrase_and_validate(
                        p_name,
                        'passphrase',
                        self.validate_passphrase,
                        auto_allowed=auto_allowed)
            elif not interactive and prompt:
                LOG.debug('Skipping interactive input for %s', p_name)
                continue

            if not passphrase:
                if passphrase_type == 'uuid':  # nosec
                    passphrase = uuidutils.generate_uuid()
                else:
                    passphrase = CryptoString(profile).get_crypto_string(
                        self._catalog.get_length(p_name))
                    if passphrase_type == 'base64':  # nosec
                        # Take the randomly generated string and convert to a
                        # random base64 string
                        passphrase = passphrase.encode()
                        passphrase = base64.b64encode(passphrase).decode()
            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, storage_policy, passphrase))
            if storage_policy == passphrase_catalog.P_ENCRYPTED:
                PeglegSecretManagement(
                    docs=docs,
                    generated=True,
                    author=self._author,
                    catalog=self._catalog).encrypt_secrets(save_path)
            else:
                files.write(docs, save_path)