wasmcloud_control_interface/types/
registry.rs

1//! Data types used when managing credentials on a wasmCloud host or during operation
2
3use anyhow::bail;
4use serde::{Deserialize, Serialize};
5
6/// Credentials for a registry that contains WebAssembly component artifacts.
7///
8/// While this is usually a docker image registry, other registries may be supported
9/// in the future.
10#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
11#[non_exhaustive]
12pub struct RegistryCredential {
13    #[serde(default, skip_serializing_if = "Option::is_none")]
14    pub(crate) password: Option<String>,
15    /// If supplied, token authentication will be used for the registry
16    #[serde(default, skip_serializing_if = "Option::is_none")]
17    pub(crate) token: Option<String>,
18    /// If supplied, username and password will be used for HTTP Basic authentication
19    #[serde(default, skip_serializing_if = "Option::is_none")]
20    pub(crate) username: Option<String>,
21    /// The type of the registry (only "oci" is supported at this time")
22    #[serde(rename = "registryType", default = "default_registry_type")]
23    pub(crate) registry_type: String,
24}
25
26impl RegistryCredential {
27    /// Create a [`RegistryCredential`] from username and password
28    #[must_use]
29    pub fn from_username_password(username: &str, password: &str, registry_type: &str) -> Self {
30        Self {
31            username: Some(username.into()),
32            password: Some(password.into()),
33            token: None,
34            registry_type: registry_type.into(),
35        }
36    }
37
38    /// Create a [`RegistryCredential`] from token
39    #[must_use]
40    pub fn from_token(token: &str, registry_type: &str) -> Self {
41        Self {
42            username: None,
43            password: None,
44            token: Some(token.into()),
45            registry_type: registry_type.into(),
46        }
47    }
48
49    #[must_use]
50    pub fn password(&self) -> Option<&str> {
51        self.password.as_deref()
52    }
53
54    #[must_use]
55    pub fn token(&self) -> Option<&str> {
56        self.token.as_deref()
57    }
58
59    #[must_use]
60    pub fn username(&self) -> Option<&str> {
61        self.username.as_deref()
62    }
63
64    #[must_use]
65    pub fn registry_type(&self) -> &str {
66        &self.registry_type
67    }
68}
69
70/// Helper for creating the default registry type
71fn default_registry_type() -> String {
72    "oci".to_string()
73}
74
75impl TryFrom<&RegistryCredential> for oci_client::secrets::RegistryAuth {
76    type Error = anyhow::Error;
77
78    fn try_from(cred: &RegistryCredential) -> Result<Self, Self::Error> {
79        if cred.registry_type != "oci" {
80            bail!("Only OCI registries are supported at this time");
81        }
82
83        match cred {
84            RegistryCredential {
85                username: Some(username),
86                password: Some(password),
87                ..
88            } => Ok(oci_client::secrets::RegistryAuth::Basic(
89                username.clone(),
90                password.clone(),
91            )),
92
93            RegistryCredential {
94                username: Some(username),
95                password: None,
96                token: Some(token),
97                ..
98            } => Ok(oci_client::secrets::RegistryAuth::Basic(
99                username.clone(),
100                token.clone(),
101            )),
102            _ => bail!("Invalid OCI registry credentials"),
103        }
104    }
105}