wasmcloud_core/
registry.rs

1use std::path::PathBuf;
2
3use anyhow::{Context as _, Result};
4
5/// The type of a registry
6#[derive(Debug, Default, Clone, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum RegistryType {
9    /// OCI registry
10    #[default]
11    Oci,
12}
13
14/// The authentication settings for a registry
15#[derive(Debug, Default, Clone, PartialEq, Eq)]
16#[non_exhaustive]
17pub enum RegistryAuth {
18    /// HTTP Basic authentication (username and password)
19    Basic(String, String),
20    /// token authentication
21    Token(String),
22    /// No authentication
23    #[default]
24    Anonymous,
25}
26
27impl From<(Option<String>, Option<String>)> for RegistryAuth {
28    fn from((maybe_username, maybe_password): (Option<String>, Option<String>)) -> Self {
29        match (maybe_username, maybe_password) {
30            (Some(username), Some(password)) => Self::Basic(username, password),
31            _ => Self::Anonymous,
32        }
33    }
34}
35
36#[cfg(feature = "oci")]
37impl From<&RegistryAuth> for oci_client::secrets::RegistryAuth {
38    fn from(auth: &crate::RegistryAuth) -> Self {
39        match auth {
40            crate::RegistryAuth::Basic(username, password) => {
41                Self::Basic(username.clone(), password.clone())
42            }
43            _ => Self::Anonymous,
44        }
45    }
46}
47
48#[cfg(feature = "oci")]
49impl From<RegistryAuth> for oci_client::secrets::RegistryAuth {
50    fn from(auth: crate::RegistryAuth) -> Self {
51        match auth {
52            crate::RegistryAuth::Basic(username, password) => Self::Basic(username, password),
53            _ => Self::Anonymous,
54        }
55    }
56}
57
58/// Credentials for a registry containing wasmCloud artifacts
59#[derive(Debug, Default)]
60#[non_exhaustive]
61pub struct RegistryConfig {
62    /// The type of the registry (only OCI is supported at this time)
63    pub(crate) reg_type: RegistryType,
64    /// The auth settings for the registry
65    pub(crate) auth: RegistryAuth,
66    /// Whether or not to allow downloading artifacts with the tag `latest`. Only valid for OCI registries
67    pub(crate) allow_latest: bool,
68    /// Whether or not to allow downloading artifacts over HTTP
69    pub(crate) allow_insecure: bool,
70    /// Additional CAs to include in the OCI client configuration
71    pub(crate) additional_ca_paths: Vec<PathBuf>,
72}
73
74/// Builder for constructing a [`RegistryConfig`]
75///
76/// While `reg_type` and `auth` are not explicitly required, they must be provided, otherwise
77/// building will fail.
78#[derive(Debug, Clone, Default)]
79#[allow(unused)]
80pub struct RegistryConfigBuilder {
81    reg_type: Option<RegistryType>,
82    auth: Option<RegistryAuth>,
83    allow_latest: Option<bool>,
84    allow_insecure: Option<bool>,
85    additional_ca_paths: Option<Vec<PathBuf>>,
86}
87
88impl RegistryConfigBuilder {
89    pub fn reg_type(mut self, rt: RegistryType) -> Self {
90        self.reg_type = Some(rt);
91        self
92    }
93
94    pub fn auth(mut self, ra: RegistryAuth) -> Self {
95        self.auth = Some(ra);
96        self
97    }
98
99    pub fn allow_latest(mut self, latest: bool) -> Self {
100        self.allow_latest = Some(latest);
101        self
102    }
103
104    pub fn allow_insecure(mut self, insecure: bool) -> Self {
105        self.allow_insecure = Some(insecure);
106        self
107    }
108
109    pub fn additional_ca_paths(mut self, acp: impl IntoIterator<Item = PathBuf>) -> Self {
110        self.additional_ca_paths = Some(acp.into_iter().collect::<Vec<PathBuf>>());
111        self
112    }
113
114    pub fn build(self) -> Result<RegistryConfig> {
115        let allow_insecure = self.allow_insecure.unwrap_or_default();
116        Ok(RegistryConfig {
117            reg_type: self.reg_type.context("missing registry type")?,
118            auth: if allow_insecure {
119                self.auth.unwrap_or_default()
120            } else {
121                self.auth.context("missing registry auth")?
122            },
123            allow_latest: self.allow_insecure.unwrap_or_default(),
124            allow_insecure,
125            additional_ca_paths: self.additional_ca_paths.unwrap_or_default(),
126        })
127    }
128}
129
130impl RegistryConfig {
131    pub fn builder() -> RegistryConfigBuilder {
132        RegistryConfigBuilder::default()
133    }
134
135    pub fn reg_type(&self) -> &RegistryType {
136        &self.reg_type
137    }
138
139    pub fn auth(&self) -> &RegistryAuth {
140        &self.auth
141    }
142
143    pub fn set_auth(&mut self, value: RegistryAuth) {
144        self.auth = value;
145    }
146
147    pub fn allow_latest(&self) -> bool {
148        self.allow_latest
149    }
150
151    pub fn set_allow_latest(&mut self, value: bool) {
152        self.allow_latest = value;
153    }
154
155    pub fn allow_insecure(&self) -> bool {
156        self.allow_insecure
157    }
158
159    pub fn set_allow_insecure(&mut self, value: bool) {
160        self.allow_insecure = value;
161    }
162
163    pub fn additional_ca_paths(&self) -> &Vec<PathBuf> {
164        &self.additional_ca_paths
165    }
166
167    pub fn set_additional_ca_paths(&mut self, value: Vec<PathBuf>) {
168        self.additional_ca_paths = value;
169    }
170}