コード例 #1
0
ファイル: client.py プロジェクト: SdgJlbl/vault-cli
    def _render_template_value(self, secret: types.JSONValue) -> types.JSONValue:
        if isinstance(secret, dict):
            return {k: self._render_template_value(v) for k, v in secret.items()}
        if not isinstance(secret, str):
            return secret

        if not secret.startswith(self.template_prefix):
            return secret

        return self.render_template(secret[len(self.template_prefix) :])
コード例 #2
0
    def set_secret(
        self,
        path: str,
        value: types.JSONValue,
        force: Optional[bool] = None,
        update: Optional[bool] = None,
    ) -> None:
        """
        Sets the value of a secret

        Parameters
        ----------
        path : str
            Path to the secret
        value : types.JSONValue
            Value of the secret
        force : Optional[bool], optional
            If safe_mode is True, whether to overwrite existing secret
        update: Optional[bool], optional
            If true then merge the value with the existing one, else overwrite it

        Raises
        ------
        exceptions.VaultOverwriteSecretError
            Cannot overwrite a secret if safe_mode is True and force is False
        exceptions.VaultMixSecretAndFolder
            Either the path is an existing folder or a parent folder is a secret
        """
        assert isinstance(value, dict)

        force = self.get_force(force)

        try:
            existing_value = self.get_secret(path=path, render=False)
            assert isinstance(existing_value, dict)
        except exceptions.VaultSecretNotFound:
            pass
        except exceptions.VaultForbidden:
            logger.warning(
                f"Read access '{path}' forbidden: if it exists, secret will be overridden."
            )
        else:
            # if we overwrite the whole mapping we can compare the value directly
            # if we update the mapping, we only have to check the updated keys
            if not update and not force and existing_value != value:
                raise exceptions.VaultOverwriteSecretError(path=path)
            if (update and not force
                    and any(existing_value[key] != value[key]
                            for key in value.keys() & existing_value.keys())):
                raise exceptions.VaultOverwriteSecretError(path=path)

            if update:
                # merge value with existing_value
                value = {**existing_value, **value}

        try:
            problematic_secrets = self.list_secrets(path=path)
            if problematic_secrets:
                secrets = [
                    f"{path}/{secret}" for secret in problematic_secrets
                ]
                raise exceptions.VaultMixSecretAndFolder(
                    f"Cannot create a secret at '{path}' because it is already a "
                    f"folder containing {', '.join(secrets)}")
        except exceptions.VaultForbidden:
            logger.info(
                f"List '{path}' forbidden: if it exists, secret will be overridden."
            )

        path = path.rstrip("/")
        for parent in list(pathlib.PurePath(path).parents)[:-1]:
            try:
                self.get_secret(str(parent), render=False)
            except exceptions.VaultSecretNotFound:
                pass
            except exceptions.VaultForbidden:
                logger.info(
                    f"Read access '{parent}' forbidden: cannot check if a secret exists here."
                )
            else:
                raise exceptions.VaultMixSecretAndFolder(
                    f"Cannot create a secret at '{path}' because '{parent}' already exists as a secret"
                )

        self._set_secret(path=self._build_full_path(path), secret=value)