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_text(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_binary(name: impl ToString, config: ByteString) -> Self {
115 let data = [(Self::DOCKER_CONFIG_JSON_KEY, config)];
116 Self::new(name)
117 .r#type(Self::SECRET_TYPE_DOCKER_CONFIG_JSON)
118 .data(data)
119 }
120
121 fn basic_auth(name: impl ToString, username: impl ToString, password: impl ToString) -> Self {
123 let data = [
124 (Self::BASIC_AUTH_USERNAME_KEY, username.to_string()),
125 (Self::BASIC_AUTH_PASSWORD_KEY, password.to_string()),
126 ];
127 Self::new(name)
128 .r#type(Self::SECRET_TYPE_BASIC_AUTH)
129 .string_data(data)
130 }
131
132 fn ssh_auth(name: impl ToString, private_key: impl ToString) -> Self {
134 let data = [(Self::SSH_AUTH_PRIVATE_KEY, private_key)];
135 Self::new(name)
136 .r#type(Self::SECRET_TYPE_SSH_AUTH)
137 .string_data(data)
138 }
139
140 fn image_pull_secret(
142 name: impl ToString,
143 registry: impl ToString,
144 username: impl ToString,
145 password: impl ToString,
146 ) -> Self {
147 let registry = registry.to_string();
148 let username = username.to_string();
149 let password = password.to_string();
150 let auth = base64::prelude::BASE64_STANDARD.encode(format!("{username}:{password}"));
151 let config = format!(
152 r#"{{"auths":{{"{registry}":{{"username":"{username}","password":"{password}","auth":"{auth}"}}}}}}"#
153 );
154 Self::docker_config_json_text(name, config)
155 }
156}
157
158pub trait SecretExt2: SecretExt {
159 #[deprecated(
162 since = "0.0.54",
163 note = "use SecretExt::docker_config_json_text instead"
164 )]
165 fn image_pull_secret(name: impl ToString, config: impl ToString) -> Self {
166 Self::docker_config_json_text(name, config)
167 }
168}
169
170impl SecretExt for corev1::Secret {
171 fn new(name: impl ToString) -> Self {
172 let metadata = metadata(name);
173 Self {
174 metadata,
175 ..default()
180 }
181 }
182
183 fn immutable(self, yes: bool) -> Self {
184 let immutable = Some(yes);
185 Self { immutable, ..self }
186 }
187
188 fn r#type(self, r#type: impl ToString) -> Self {
189 let type_ = Some(r#type.to_string());
190 Self { type_, ..self }
191 }
192
193 fn data(mut self, data: impl IntoIterator<Item = (impl ToString, ByteString)>) -> Self {
194 let iter = data
195 .into_iter()
196 .map(|(key, value)| (key.to_string(), value));
197 self.data.get_or_insert_default().extend(iter);
198 self
199 }
200
201 fn string_data(
202 mut self,
203 data: impl IntoIterator<Item = (impl ToString, impl ToString)>,
204 ) -> Self {
205 let iter = data
206 .into_iter()
207 .map(|(key, value)| (key.to_string(), value.to_string()));
208 self.string_data.get_or_insert_default().extend(iter);
209 self
210 }
211}
212
213impl SecretExt2 for corev1::Secret {}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 use serde_json as json;
220
221 #[test]
222 fn image_pull_secret() {
223 let secret = <corev1::Secret as SecretExt>::image_pull_secret(
224 "name", "registry", "username", "password",
225 );
226 let string_data = secret.string_data.unwrap_or_default();
227 assert_eq!(string_data.len(), 1);
228 let config: json::Value =
229 json::from_str(&string_data[corev1::Secret::DOCKER_CONFIG_JSON_KEY]).unwrap();
230 assert!(config.is_object());
231 }
232
233 #[test]
234 fn ssh_auth() {
235 let secret = corev1::Secret::ssh_auth(
236 "name",
237 "KGpwKaqlGas+LaAqdwdfAAAEEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIClTFvhvwp1UH25b",
238 );
239 let string_data = secret.string_data.unwrap_or_default();
240 assert_eq!(string_data.len(), 1);
241 assert_eq!(string_data[corev1::Secret::SSH_AUTH_PRIVATE_KEY].len(), 70);
242 }
243}