Skip to main content

pg_embedded_setup_unpriv/extensions/manifest/
source.rs

1//! Where the manifest comes from and how its bytes are pinned.
2//!
3//! Its own module because the enum and its rendering are the one place the
4//! redaction rule is stated, and it belongs beside the reader that consumes
5//! it rather than in the feature's root.
6
7use camino::Utf8PathBuf;
8
9use crate::extensions::{Sha256Hex, http};
10
11/// Where the manifest comes from and how it is verified.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum ManifestSource {
14    /// Fetched from a permitted URL: `https://` anywhere, or `http://` to a
15    /// loopback address. The digest is mandatory either way, because it is
16    /// what makes the fetched bytes checkable and loopback does not supply
17    /// that. See [`crate::extensions::is_permitted_url`], which the fetch and the redirect
18    /// policy both consult.
19    Url {
20        /// The URL of `manifest.json`.
21        url: String,
22        /// Expected SHA-256 of the manifest bytes.
23        sha256: Sha256Hex,
24    },
25    /// Read from the filesystem; a local manifest is trusted like local source,
26    /// so the digest is optional.
27    Path {
28        /// Path of `manifest.json`.
29        path: Utf8PathBuf,
30        /// Expected SHA-256 of the manifest bytes, when pinned.
31        sha256: Option<Sha256Hex>,
32    },
33}
34
35impl ManifestSource {
36    /// Renders the location for error messages and logs.
37    ///
38    /// A URL is redacted, because a consumer's manifest URL can carry
39    /// userinfo, a signed query parameter or a token in its fragment, and this
40    /// string reaches log fields and error messages. A path is rendered as
41    /// written.
42    ///
43    /// # Examples
44    ///
45    /// ```
46    /// use camino::Utf8PathBuf;
47    /// use pg_embedded_setup_unpriv::extensions::ManifestSource;
48    ///
49    /// let path = ManifestSource::Path {
50    ///     path: Utf8PathBuf::from("/srv/extensions/manifest.json"),
51    ///     sha256: None,
52    /// };
53    /// assert_eq!(path.location(), "/srv/extensions/manifest.json");
54    /// ```
55    #[must_use]
56    pub fn location(&self) -> String {
57        match self {
58            // Redacted: this is used in log fields and error messages, and a
59            // consumer's URL can carry userinfo or a signed query parameter.
60            Self::Url { url, .. } => http::redact_url(url),
61            Self::Path { path, .. } => path.to_string(),
62        }
63    }
64}