hc_vault/kubernetes/
auth.rs1use serde::{Deserialize, Serialize};
2use std::time::SystemTime;
3use url::Url;
4
5use crate::internals;
6use crate::Auth as AuthTrait;
7use crate::Error;
8
9#[derive(Clone, Serialize)]
11pub struct KubernetesLogin {
12 pub jwt: String,
14 pub role: String,
16}
17
18#[derive(Deserialize)]
19#[allow(dead_code)]
20struct KubernetesMetadata {
21 role: String,
22 service_account_name: String,
23 service_account_namespace: String,
24 service_account_secret_name: String,
25 service_account_uid: String,
26}
27
28#[derive(Deserialize)]
29#[allow(dead_code)]
30struct KubernetesAuth {
31 client_token: String,
32 accessor: String,
33 policies: Vec<String>,
34 metadata: KubernetesMetadata,
35 lease_duration: u64,
36 renewable: bool,
37}
38
39#[derive(Deserialize)]
40struct KubernetesResponse {
41 auth: KubernetesAuth,
42}
43
44#[derive(Deserialize)]
45#[allow(dead_code)]
46struct GeneralAuth {
47 client_token: String,
48 policies: Vec<String>,
49 lease_duration: u64,
50 renewable: bool,
51}
52
53#[derive(Deserialize)]
54struct RenewResponse {
55 auth: GeneralAuth,
56}
57
58pub struct Session {
61 kubernetes: KubernetesLogin,
62 token: internals::TokenContainer,
63}
64
65impl AuthTrait for Session {
66 fn is_expired(&self) -> bool {
67 let start_time = self.token.get_start();
68 let current_time = SystemTime::now()
69 .duration_since(SystemTime::UNIX_EPOCH)
70 .unwrap()
71 .as_secs();
72
73 let elapsed = current_time - start_time;
74 let duration = self.token.get_duration();
75
76 elapsed >= duration
77 }
78
79 fn get_token(&self) -> String {
80 match self.token.get_token() {
85 None => String::from(""),
86 Some(s) => s,
87 }
88 }
89
90 fn auth(&self, vault_url: &str) -> Result<(), Error> {
91 let mut login_url = match Url::parse(vault_url) {
92 Err(e) => return Err(Error::from(e)),
93 Ok(url) => url,
94 };
95 login_url = match login_url.join("v1/auth/kubernetes/login") {
96 Err(e) => return Err(Error::from(e)),
97 Ok(u) => u,
98 };
99
100 let http_client = reqwest::blocking::Client::new();
101 let response = match http_client.post(login_url).json(&self.kubernetes).send() {
102 Err(e) => return Err(Error::from(e)),
103 Ok(resp) => resp,
104 };
105
106 let status_code = response.status().as_u16();
107 if status_code != 200 && status_code != 204 {
108 return Err(Error::from(status_code));
109 }
110
111 let data = match response.json::<KubernetesResponse>() {
112 Err(e) => Err(Error::from(e)),
113 Ok(json) => Ok(json),
114 };
115
116 let data = data.unwrap();
117
118 let token = data.auth.client_token;
119 let current_time = SystemTime::now()
120 .duration_since(SystemTime::UNIX_EPOCH)
121 .unwrap()
122 .as_secs();
123 let duration = data.auth.lease_duration;
124
125 self.token.set_token(token);
130
131 self.token.set_renewable(data.auth.renewable);
132
133 self.token.set_start(current_time);
138 self.token.set_duration(duration);
139
140 Ok(())
141 }
142
143 fn is_renewable(&self) -> bool {
144 self.token.get_renewable()
145 }
146
147 fn get_total_duration(&self) -> u64 {
148 self.token.get_duration()
149 }
150
151 fn renew(&self, vault_url: &str) -> Result<(), Error> {
152 let mut renew_url = match Url::parse(vault_url) {
153 Err(e) => {
154 return Err(Error::from(e));
155 }
156 Ok(url) => url,
157 };
158 renew_url = match renew_url.join("v1/auth/token/renew-self") {
159 Err(e) => {
160 return Err(Error::from(e));
161 }
162 Ok(u) => u,
163 };
164
165 let http_client = reqwest::blocking::Client::new();
166 let res = http_client
167 .post(renew_url)
168 .header("X-Vault-Token", self.token.get_token().unwrap())
169 .send();
170
171 let response = match res {
172 Err(e) => {
173 return Err(Error::from(e));
174 }
175 Ok(resp) => resp,
176 };
177
178 let status_code = response.status().as_u16();
179 if status_code != 200 && status_code != 204 {
180 return Err(Error::from(status_code));
181 }
182
183 let data = match response.json::<RenewResponse>() {
184 Err(e) => Err(Error::from(e)),
185 Ok(json) => Ok(json),
186 };
187
188 let data = data.unwrap();
189
190 let current_time = SystemTime::now()
191 .duration_since(SystemTime::UNIX_EPOCH)
192 .unwrap()
193 .as_secs();
194 let duration = data.auth.lease_duration;
195 let renewable = data.auth.renewable;
196
197 self.token.set_renewable(renewable);
198
199 self.token.set_start(current_time);
201 self.token.set_duration(duration);
202
203 Ok(())
204 }
205}
206
207impl Session {
208 pub fn new(role: String, jwt: String) -> Result<Session, Error> {
211 Ok(Session {
212 kubernetes: KubernetesLogin { role, jwt },
213 token: internals::TokenContainer::new(),
214 })
215 }
216}