microsandbox_types/cloud/
secrets.rs1use serde::{Deserialize, Serialize};
4use zeroize::Zeroizing;
5
6use crate::compat;
7use crate::domain::{
8 HostPattern, SecretEntry, SecretSubstitution, SecretViolationAction, SecretsConfig,
9};
10use crate::modify::SecretSource;
11
12#[derive(Debug, Clone, Default, Serialize)]
18#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
19#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
20pub struct CloudSecretsConfig {
21 #[serde(default)]
23 pub entries: Vec<CloudSecretEntry>,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub passthrough_hosts: Option<Vec<CloudHostPattern>>,
28 #[serde(default)]
30 pub violation_action: CloudViolationAction,
31}
32
33#[derive(Debug, Clone, Serialize)]
35#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
36#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
37pub struct CloudSecretEntry {
38 pub env_var: String,
40 #[serde(default)]
42 pub value: String,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub source: Option<CloudSecretSource>,
46 pub placeholder: String,
48 #[serde(default)]
50 pub allowed_hosts: Vec<CloudHostPattern>,
51 #[serde(default)]
53 pub substitution: SecretSubstitution,
54 #[serde(default)]
56 pub passthrough_hosts: Vec<CloudHostPattern>,
57 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub violation_action: Option<CloudViolationAction>,
60 #[serde(default)]
62 #[cfg_attr(feature = "utoipa", schema(default = true))]
63 pub require_tls_identity: bool,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
69#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
70#[serde(tag = "type", rename_all = "snake_case")]
71pub enum CloudSecretSource {
72 Env {
74 var: String,
76 },
77 Store {
79 reference: String,
81 },
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
87#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
88#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
89#[serde(tag = "type", rename_all = "snake_case")]
90pub enum CloudHostPattern {
91 Exact {
93 value: String,
95 },
96 Wildcard {
98 value: String,
100 },
101 Any,
103}
104
105#[derive(Debug, Clone, Default, Serialize, Deserialize)]
107#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
108#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
109#[serde(tag = "type", rename_all = "snake_case")]
110pub enum CloudViolationAction {
111 Block,
113 #[default]
115 BlockAndLog,
116 BlockAndTerminate,
118}
119
120impl<'de> Deserialize<'de> for CloudSecretsConfig {
125 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
126 compat::cloud::deserialize_secrets_config(deserializer)
127 }
128}
129
130impl<'de> Deserialize<'de> for CloudSecretEntry {
131 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
132 compat::cloud::deserialize_secret_entry(deserializer)
133 }
134}
135
136impl From<HostPattern> for CloudHostPattern {
141 fn from(pattern: HostPattern) -> Self {
142 match pattern {
143 HostPattern::Exact(value) => Self::Exact { value },
144 HostPattern::Wildcard(value) => Self::Wildcard { value },
145 HostPattern::Any => Self::Any,
146 }
147 }
148}
149
150impl From<CloudHostPattern> for HostPattern {
151 fn from(pattern: CloudHostPattern) -> Self {
152 match pattern {
153 CloudHostPattern::Exact { value } => Self::Exact(value),
154 CloudHostPattern::Wildcard { value } => Self::Wildcard(value),
155 CloudHostPattern::Any => Self::Any,
156 }
157 }
158}
159
160impl From<SecretViolationAction> for CloudViolationAction {
161 fn from(action: SecretViolationAction) -> Self {
162 match action {
163 SecretViolationAction::Block => Self::Block,
164 SecretViolationAction::BlockAndLog => Self::BlockAndLog,
165 SecretViolationAction::BlockAndTerminate => Self::BlockAndTerminate,
166 }
167 }
168}
169
170impl From<CloudViolationAction> for SecretViolationAction {
171 fn from(action: CloudViolationAction) -> Self {
172 match action {
173 CloudViolationAction::Block => Self::Block,
174 CloudViolationAction::BlockAndLog => Self::BlockAndLog,
175 CloudViolationAction::BlockAndTerminate => Self::BlockAndTerminate,
176 }
177 }
178}
179
180impl From<SecretSource> for CloudSecretSource {
181 fn from(source: SecretSource) -> Self {
182 match source {
183 SecretSource::Env { var } => Self::Env { var },
184 SecretSource::Store { reference } => Self::Store { reference },
185 }
186 }
187}
188
189impl From<CloudSecretSource> for SecretSource {
190 fn from(source: CloudSecretSource) -> Self {
191 match source {
192 CloudSecretSource::Env { var } => Self::Env { var },
193 CloudSecretSource::Store { reference } => Self::Store { reference },
194 }
195 }
196}
197
198impl From<SecretEntry> for CloudSecretEntry {
199 fn from(entry: SecretEntry) -> Self {
200 Self {
201 env_var: entry.env_var,
202 value: entry.value.to_string(),
203 source: entry.source.map(Into::into),
204 placeholder: entry.placeholder,
205 allowed_hosts: entry.allowed_hosts.into_iter().map(Into::into).collect(),
206 substitution: entry.substitution,
207 passthrough_hosts: entry
208 .passthrough_hosts
209 .into_iter()
210 .map(Into::into)
211 .collect(),
212 violation_action: entry.violation_action.map(Into::into),
213 require_tls_identity: entry.require_tls_identity,
214 }
215 }
216}
217
218impl From<CloudSecretEntry> for SecretEntry {
219 fn from(entry: CloudSecretEntry) -> Self {
220 Self {
221 env_var: entry.env_var,
222 value: Zeroizing::new(entry.value),
223 source: entry.source.map(Into::into),
224 placeholder: entry.placeholder,
225 allowed_hosts: entry.allowed_hosts.into_iter().map(Into::into).collect(),
226 substitution: entry.substitution,
227 passthrough_hosts: entry
228 .passthrough_hosts
229 .into_iter()
230 .map(Into::into)
231 .collect(),
232 violation_action: entry.violation_action.map(Into::into),
233 require_tls_identity: entry.require_tls_identity,
234 }
235 }
236}
237
238impl From<SecretsConfig> for CloudSecretsConfig {
239 fn from(config: SecretsConfig) -> Self {
240 Self {
241 entries: config.secrets.into_iter().map(Into::into).collect(),
242 passthrough_hosts: config
243 .passthrough_hosts
244 .map(|hosts| hosts.into_iter().map(Into::into).collect()),
245 violation_action: config.violation_action.into(),
246 }
247 }
248}
249
250impl From<CloudSecretsConfig> for SecretsConfig {
251 fn from(config: CloudSecretsConfig) -> Self {
252 Self {
253 secrets: config.entries.into_iter().map(Into::into).collect(),
254 passthrough_hosts: config
255 .passthrough_hosts
256 .map(|hosts| hosts.into_iter().map(Into::into).collect()),
257 violation_action: config.violation_action.into(),
258 }
259 }
260}