예제 #1
0
    def render_template(
            self,
            template: str,
            search_path: pathlib.Path = pathlib.Path("."),
    ) -> str:
        """
        Renders a template to a string, giving it access to a `vault` function
        that can read from the vault

        Parameters
        ----------
        template : str
            Jinja template string
        render : bool, optional
            Whether template secrets should be rendered, by default True
        search_path: pathlib.Path object, optional
            search path for additional Jinja2 templates, by default current working directory
            See https://jinja.palletsprojects.com/en/2.10.x/api/#jinja2.FileSystemLoader

        Returns
        -------
        str
            The rendered template

        Raises
        ------
        exceptions.VaultRenderTemplateError
            If a secret is not found or access is forbidden
        """
        def vault(path):
            try:
                return self.get_secret(path)
            except exceptions.VaultException as exc:
                raise exceptions.VaultRenderTemplateError(
                    "Error while rendering template") from exc

        env = jinja2.sandbox.SandboxedEnvironment(
            loader=jinja2.FileSystemLoader(search_path.as_posix()),
            keep_trailing_newline=True,
        )
        try:
            return env.from_string(template).render(vault=vault)
        except jinja2.exceptions.SecurityError as exc:
            raise exceptions.VaultRenderTemplateError(
                "Jinja2 template security error") from exc
        except jinja2.exceptions.TemplateSyntaxError as exc:
            raise exceptions.VaultRenderTemplateError(
                "Jinja2 template syntax error") from exc
예제 #2
0
    def get_secret(self,
                   path: str,
                   key: Optional[str] = None,
                   render: bool = True
                   ) -> Union[types.JSONValue, utils.RecursiveValue]:
        """
        Retrieve the value of a single secret

        Parameters
        ----------
        path : str
            Path of the secret

        key : str, optional
            If set, return only this key

        render : bool, optional
            Whether to render templated secret or not, by default True

        Returns
        -------
        types.JSONValue
            Secret value
        """
        full_path = self._build_full_path(path)
        if full_path in self._currently_fetching:
            return utils.RecursiveValue(path)

        self._currently_fetching.add(full_path)
        try:
            assert self.cache is not None
            try:
                mapping = self.cache[full_path]
            except KeyError:
                mapping = self.cache[full_path] = self._get_secret(
                    path=full_path)

            if mapping and render and self.render:
                try:
                    mapping = self._render_template_dict(mapping)
                except exceptions.VaultRenderTemplateError as exc:
                    message = f'Error while rendering secret at path "{path}"'
                    raise exceptions.VaultRenderTemplateError(message) from exc

        finally:
            self._currently_fetching.remove(full_path)

        if key is not None:
            try:
                secret = mapping[key]
            except KeyError:
                raise exceptions.VaultSecretNotFound(errors=[
                    f"Key '{key}' not found in secret at path '{full_path}'"
                ])
        else:
            secret = mapping

        return secret
예제 #3
0
    def _render_template_dict(
            self,
            secrets: Dict[str, types.JSONValue]) -> Dict[str, types.JSONValue]:
        result = {}
        for key, value in secrets.items():
            try:
                result[key] = self._render_template_value(value)
            except exceptions.VaultRenderTemplateError as exc:
                message = f'Error while rendering secret value for key "{key}"'
                raise exceptions.VaultRenderTemplateError(message) from exc

        return result
예제 #4
0
 def vault(path):
     try:
         return self.get_secret(path, render=render)
     except exceptions.VaultException as exc:
         raise exceptions.VaultRenderTemplateError(
             "Error while rendering template") from exc
예제 #5
0
파일: client.py 프로젝트: SdgJlbl/vault-cli
 def vault(path):
     try:
         return self.get_secret(path, render=render)
     except exceptions.VaultException:
         raise exceptions.VaultRenderTemplateError(f"'{path}' not found")
예제 #6
0
def test_vault_render_template_error():
    assert (
        str(exceptions.VaultRenderTemplateError("yay"))
        == "VaultRenderTemplateError: Error while rendering template: yay"
    )
예제 #7
0
def test_vault_render_template_error():
    assert str(exceptions.VaultRenderTemplateError("yay")) == "yay"