Skip to main content

csaf_walker/model/
metadata.rs

1use chrono::{DateTime, Utc};
2use url::Url;
3
4#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
5pub struct Distribution {
6    #[serde(default, skip_serializing_if = "Option::is_none")]
7    pub directory_url: Option<Url>,
8    #[serde(default, skip_serializing_if = "Option::is_none")]
9    pub rolie: Option<Rolie>,
10}
11
12#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
13pub struct Rolie {
14    #[serde(default)]
15    pub categories: Vec<Url>,
16    #[serde(default, skip_serializing_if = "Vec::is_empty")]
17    pub feeds: Vec<Feed>,
18    #[serde(default)]
19    pub services: Vec<Url>,
20}
21
22#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
23pub struct Feed {
24    #[serde(default, skip_serializing_if = "Option::is_none")]
25    pub summary: Option<String>,
26    pub tlp_label: TlpLabel,
27    pub url: Url,
28}
29
30#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
31#[serde(rename_all = "UPPERCASE")]
32pub enum TlpLabel {
33    Unlabeled,
34    White,
35    Green,
36    Amber,
37    Red,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
41pub struct Key {
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub fingerprint: Option<String>,
44    pub url: Url,
45}
46
47impl<'a> From<&'a Key> for walker_common::validate::source::Key<'a> {
48    fn from(value: &'a Key) -> Self {
49        walker_common::validate::source::Key {
50            fingerprint: value.fingerprint.as_deref(),
51            url: &value.url,
52        }
53    }
54}
55
56#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
57pub struct Publisher {
58    pub category: PublisherCategory,
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub contact_details: Option<String>,
61    #[serde(default, skip_serializing_if = "Option::is_none")]
62    pub issuing_authority: Option<String>,
63    pub name: String,
64    pub namespace: String,
65}
66
67#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
68#[serde(rename_all = "snake_case")]
69pub enum PublisherCategory {
70    Coordinator,
71    Discoverer,
72    Other,
73    Translator,
74    User,
75    Vendor,
76    #[serde(untagged)]
77    Unknown(String),
78}
79
80#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
81pub enum MetadataVersion {
82    #[serde(rename = "2.0")]
83    V2_0,
84    #[serde(untagged)]
85    Unknown(String),
86}
87
88#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
89pub struct ProviderMetadata {
90    pub canonical_url: Url,
91
92    #[serde(default)]
93    pub distributions: Vec<Distribution>,
94
95    pub last_updated: DateTime<Utc>,
96
97    #[serde(rename = "list_on_CSAF_aggregators")]
98    #[serde(default)]
99    pub list_on_csaf_aggregators: bool,
100
101    pub metadata_version: MetadataVersion,
102
103    #[serde(rename = "mirror_on_CSAF_aggregators")]
104    #[serde(default)]
105    pub mirror_on_csaf_aggregators: bool,
106
107    #[serde(default)]
108    pub public_openpgp_keys: Vec<Key>,
109
110    pub publisher: Publisher,
111
112    /// Contains the role of the issuing party according to section 7 in the CSAF standard.
113    #[serde(default = "default_role")]
114    pub role: Role,
115}
116
117const fn default_role() -> Role {
118    Role::Provider
119}
120
121#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
122pub enum Role {
123    #[serde(rename = "csaf_publisher")]
124    Publisher,
125    #[serde(rename = "csaf_provider")]
126    Provider,
127    #[serde(rename = "csaf_trusted_provider")]
128    TrustedProvider,
129}