k8s_openapi_ext/ext/
secret.rs1use base64::Engine;
2
3use super::*;
4
5pub trait SecretExt: super::ResourceBuilder + Sized {
6 const SECRET_TYPE_OPAQUE: &str = "Opaque";
8
9 const SECRET_TYPE_SERVICE_ACCOUNT_TOKEN: &str = "kubernetes.io/service-account-token";
16
17 const SERVICE_ACCOUNT_NAME_KEY: &str = "kubernetes.io/service-account.name";
19 const SERVICE_ACCOUNT_UID_KEY: &str = "kubernetes.io/service-account.uid";
21 const SERVICE_ACCOUNT_TOKEN_KEY: &str = "token";
23 const SERVICE_ACCOUNT_KUBECONFIG_KEY: &str = "kubernetes.kubeconfig";
25 const SERVICE_ACCOUNT_ROOTCA_KEY: &str = "ca.crt";
27 const SERVICE_ACCOUNT_NAMESPACE_KEY: &str = "namespace";
29
30 const SECRET_TYPE_DOCKERCFG: &str = "kubernetes.io/dockercfg";
35
36 const DOCKER_CONFIG_KEY: &str = ".dockercfg";
38
39 const SECRET_TYPE_DOCKER_CONFIG_JSON: &str = "kubernetes.io/dockerconfigjson";
44 const DOCKER_CONFIG_JSON_KEY: &str = ".dockerconfigjson";
46
47 const SECRET_TYPE_BASIC_AUTH: &str = "kubernetes.io/basic-auth";
53
54 const BASIC_AUTH_USERNAME_KEY: &str = "username";
56 const BASIC_AUTH_PASSWORD_KEY: &str = "password";
58
59 const SECRET_TYPE_SSH_AUTH: &str = "kubernetes.io/ssh-auth";
64
65 const SSH_AUTH_PRIVATE_KEY: &str = "ssh-privatekey";
67
68 const SECRET_TYPE_TLS: &str = "kubernetes.io/tls";
76
77 const TLS_CERT_KEY: &str = "tls.crt";
79 const TLS_PRIVATE_KEY_KEY: &str = "tls.key";
81
82 const SECRET_TYPE_BOOTSTRAP_TOKEN: &str = "bootstrap.kubernetes.io/token";
86
87 fn new(name: impl ToString) -> Self;
89
90 fn immutable(self, yes: bool) -> Self;
92
93 fn r#type(self, r#type: impl ToString) -> Self;
94
95 fn data(self, data: impl IntoIterator<Item = (impl ToString, ByteString)>) -> Self;
96
97 fn string_data(self, data: impl IntoIterator<Item = (impl ToString, impl ToString)>) -> Self;
98
99 fn opaque(name: impl ToString) -> Self {
101 Self::new(name).r#type(Self::SECRET_TYPE_OPAQUE)
102 }
103
104 fn docker_config_json(name: impl ToString, config: impl ToString) -> Self {
107 let data = [(Self::DOCKER_CONFIG_JSON_KEY, config)];
108 Self::new(name)
109 .r#type(Self::SECRET_TYPE_DOCKER_CONFIG_JSON)
110 .string_data(data)
111 }
112
113 fn docker_config_json_base64_encoded(name: impl ToString, config: ByteString) -> Self {
116 let data = [(Self::DOCKER_CONFIG_JSON_KEY, config)];
117 Self::new(name)
118 .r#type(Self::SECRET_TYPE_DOCKER_CONFIG_JSON)
119 .data(data)
120 }
121
122 fn basic_auth(name: impl ToString, username: impl ToString, password: impl ToString) -> Self {
124 let data = [
125 (Self::BASIC_AUTH_USERNAME_KEY, username.to_string()),
126 (Self::BASIC_AUTH_PASSWORD_KEY, password.to_string()),
127 ];
128 Self::new(name)
129 .r#type(Self::SECRET_TYPE_BASIC_AUTH)
130 .string_data(data)
131 }
132
133 fn ssh_auth(name: impl ToString, private_key: impl ToString) -> Self {
135 let data = [(Self::SSH_AUTH_PRIVATE_KEY, private_key)];
136 Self::new(name)
137 .r#type(Self::SECRET_TYPE_SSH_AUTH)
138 .string_data(data)
139 }
140
141 fn image_pull_secret(
143 name: impl ToString,
144 registry: impl ToString,
145 username: impl ToString,
146 password: impl ToString,
147 ) -> Self {
148 let registry = registry.to_string();
149 let username = username.to_string();
150 let password = password.to_string();
151 let auth = base64::prelude::BASE64_STANDARD.encode(format!("{username}:{password}"));
152 let config = format!(
153 r#"{{"auths":{{"{registry}":{{"username":"{username}","password":"{password}","auth":"{auth}"}}}}}}"#
154 );
155 Self::docker_config_json(name, config)
156 }
157}
158
159pub trait SecretExt2: SecretExt {
160 #[deprecated(since = "0.0.54", note = "use SecretExt::docker_config_json instead")]
163 fn image_pull_secret(name: impl ToString, config: impl ToString) -> Self {
164 Self::docker_config_json(name, config)
165 }
166}
167
168impl SecretExt for corev1::Secret {
169 fn new(name: impl ToString) -> Self {
170 let metadata = metadata(name);
171 Self {
172 metadata,
173 ..default()
178 }
179 }
180
181 fn immutable(self, yes: bool) -> Self {
182 let immutable = Some(yes);
183 Self { immutable, ..self }
184 }
185
186 fn r#type(self, r#type: impl ToString) -> Self {
187 let type_ = Some(r#type.to_string());
188 Self { type_, ..self }
189 }
190
191 fn data(mut self, data: impl IntoIterator<Item = (impl ToString, ByteString)>) -> Self {
192 let iter = data
193 .into_iter()
194 .map(|(key, value)| (key.to_string(), value));
195 self.data.get_or_insert_default().extend(iter);
196 self
197 }
198
199 fn string_data(
200 mut self,
201 data: impl IntoIterator<Item = (impl ToString, impl ToString)>,
202 ) -> Self {
203 let iter = data
204 .into_iter()
205 .map(|(key, value)| (key.to_string(), value.to_string()));
206 self.string_data.get_or_insert_default().extend(iter);
207 self
208 }
209}
210
211impl SecretExt2 for corev1::Secret {}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 use serde_json as json;
218
219 #[test]
220 fn image_pull_secret() {
221 let secret = <corev1::Secret as SecretExt>::image_pull_secret(
222 "name", "registry", "username", "password",
223 );
224 let string_data = secret.string_data.unwrap_or_default();
225 assert_eq!(string_data.len(), 1);
226 let config: json::Value =
227 json::from_str(&string_data[corev1::Secret::DOCKER_CONFIG_JSON_KEY]).unwrap();
228 assert!(config.is_object());
229 }
230
231 #[test]
232 fn ssh_auth() {
233 let secret = corev1::Secret::ssh_auth(
234 "name",
235 "KGpwKaqlGas+LaAqdwdfAAAEEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIClTFvhvwp1UH25b",
236 );
237 let string_data = secret.string_data.unwrap_or_default();
238 assert_eq!(string_data.len(), 1);
239 assert_eq!(string_data[corev1::Secret::SSH_AUTH_PRIVATE_KEY].len(), 70);
240 }
241}