From 495c5ac42906db886f721533baccc614b0875cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 3 Feb 2026 12:56:50 +0100 Subject: [PATCH] Refactor builtin policies --- .../sigsum-generic-2025-1.builtin-policy | 0 .../sigsum-test-2025-3.builtin-policy | 0 .../sigsum-test1-2025.builtin-policy | 0 .../sigsum-test2-2025.builtin-policy | 0 src/policy/builtin.rs | 109 ++++++++++++++---- src/policy/mod.rs | 13 +++ 6 files changed, 99 insertions(+), 23 deletions(-) rename {src/policy => builtin-policies}/sigsum-generic-2025-1.builtin-policy (100%) rename {src/policy => builtin-policies}/sigsum-test-2025-3.builtin-policy (100%) rename {src/policy => builtin-policies}/sigsum-test1-2025.builtin-policy (100%) rename {src/policy => builtin-policies}/sigsum-test2-2025.builtin-policy (100%) diff --git a/src/policy/sigsum-generic-2025-1.builtin-policy b/builtin-policies/sigsum-generic-2025-1.builtin-policy similarity index 100% rename from src/policy/sigsum-generic-2025-1.builtin-policy rename to builtin-policies/sigsum-generic-2025-1.builtin-policy diff --git a/src/policy/sigsum-test-2025-3.builtin-policy b/builtin-policies/sigsum-test-2025-3.builtin-policy similarity index 100% rename from src/policy/sigsum-test-2025-3.builtin-policy rename to builtin-policies/sigsum-test-2025-3.builtin-policy diff --git a/src/policy/sigsum-test1-2025.builtin-policy b/builtin-policies/sigsum-test1-2025.builtin-policy similarity index 100% rename from src/policy/sigsum-test1-2025.builtin-policy rename to builtin-policies/sigsum-test1-2025.builtin-policy diff --git a/src/policy/sigsum-test2-2025.builtin-policy b/builtin-policies/sigsum-test2-2025.builtin-policy similarity index 100% rename from src/policy/sigsum-test2-2025.builtin-policy rename to builtin-policies/sigsum-test2-2025.builtin-policy diff --git a/src/policy/builtin.rs b/src/policy/builtin.rs index ef22c59..13d68cf 100644 --- a/src/policy/builtin.rs +++ b/src/policy/builtin.rs @@ -1,31 +1,94 @@ +//! Built-in policies for Sigsum. +//! +//! This module contains all the included built-in policies. These can be accessed +//! and used directly as public statics, or looked up at runtime by name via +//! [`Policy::builtin`]. + +use std::ops::Deref; +use std::sync::LazyLock; + use super::Policy; -const SIGSUM_TEST1_2025: &str = include_str!("sigsum-test1-2025.builtin-policy"); -const SIGSUM_TEST2_2025: &str = include_str!("sigsum-test2-2025.builtin-policy"); -const SIGSUM_TEST_2025_3: &str = include_str!("sigsum-test-2025-3.builtin-policy"); -const SIGSUM_GENERIC_2025_1: &str = include_str!("sigsum-generic-2025-1.builtin-policy"); - -impl Policy { - pub fn builtin(name: &str) -> Option { - match name { - "sigsum-test1-2025" => Some(Policy::parse(SIGSUM_TEST1_2025).unwrap()), - "sigsum-test2-2025" => Some(Policy::parse(SIGSUM_TEST2_2025).unwrap()), - "sigsum-test-2025-3" => Some(Policy::parse(SIGSUM_TEST_2025_3).unwrap()), - "sigsum-generic-2025-1" => Some(Policy::parse(SIGSUM_GENERIC_2025_1).unwrap()), - _ => None, - } +/// A built-in policy with a given name. +/// +/// The user facing name of this policy can be accessed via the public `name` field. +/// This struct implements `Deref`, so using it as a [`Policy`] becomes +/// transparent. +/// +/// This policy is parsed and lazily initialized on first use. +pub struct BuiltInPolicy { + /// The user-friendly name of the built-in policy. + pub name: &'static str, + + policy: LazyLock, +} + +impl BuiltInPolicy { + /// Returns the policy for this built-in policy. Can also be accessed + /// via the `Deref` implementation. + pub fn policy(&self) -> &Policy { + &self.policy } } -#[cfg(test)] -mod tests { - use super::*; +impl Deref for BuiltInPolicy { + type Target = Policy; - #[test] - fn parse_builtin_policies() { - assert!(Policy::builtin("sigsum-test1-2025").is_some()); - assert!(Policy::builtin("sigsum-test2-2025").is_some()); - assert!(Policy::builtin("sigsum-test-2025-3").is_some()); - assert!(Policy::builtin("sigsum-generic-2025-1").is_some()); + fn deref(&self) -> &Self::Target { + self.policy() } } + +macro_rules! define_builtin_policies { + ($( + $const_name:ident = $policy_name:literal + ),* $(,)?) => { + // Define the static constants + $( + pub static $const_name: BuiltInPolicy = BuiltInPolicy { + name: $policy_name, + policy: LazyLock::new(|| { + Policy::parse(include_str!(concat!( + "../../builtin-policies/", + $policy_name, + ".builtin-policy" + ))) + .expect(concat!("Failed to parse built-in policy: ", $policy_name)) + }), + }; + )* + + /// Returns a built-in policy by name, if one exists. + /// Only intended to be used internally by [`Policy::builtin`]. + pub(crate) fn builtin(name: &str) -> Option<&'static Policy> { + match name { + $( + $policy_name => Some(&$const_name.policy()), + )* + _ => None, + } + } + + // Auto-generate tests. Asserts that all policies parse without panicking + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn parse_builtin_policies() { + $( + let _policy = $const_name.policy(); + )* + } + } + }; +} + +// All built-in policies defined here in one single place. +// Multiple invocations not possible since this invocation emits the `builtin` lookup function. +define_builtin_policies! { + SIGSUM_TEST1_2025 = "sigsum-test1-2025", + SIGSUM_TEST2_2025 = "sigsum-test2-2025", + SIGSUM_TEST_2025_3 = "sigsum-test-2025-3", + SIGSUM_GENERIC_2025_1 = "sigsum-generic-2025-1", +} diff --git a/src/policy/mod.rs b/src/policy/mod.rs index 79b90d8..11ab9e9 100644 --- a/src/policy/mod.rs +++ b/src/policy/mod.rs @@ -3,6 +3,8 @@ use std::collections::HashMap; use crate::crypto::{Hash, PublicKey}; mod builtin; +pub use builtin::*; + mod parsing; pub use parsing::ParsePolicyError; @@ -11,6 +13,9 @@ pub use parsing::ParsePolicyError; /// /// The Sigsum policy dictates if a signed tree head is considered valid (and by extension, if a /// Sigsum signature is valid). +/// +/// This library contains a bunch of built-in policies. They can be accessed as statics +/// in this module, or looked up at runtime via [`Policy::builtin`]. #[derive(Debug, Eq, PartialEq)] pub struct Policy { // logs keeps the list of log keys and URLs indexed by keyhash. @@ -57,6 +62,14 @@ impl<'a> Iterator for Logs<'a> { } impl Policy { + /// Returns a built-in policy by name, if one exists. + /// + /// All built-in policies are also exposed as statics directly in the + /// [`policy`](crate::policy) module. + pub fn builtin(name: &str) -> Option<&'static Self> { + builtin::builtin(name) + } + pub fn logs(&self) -> Logs<'_> { Logs { inner: self.logs.iter(),