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}