Skip to content

Commit 96ca26d

Browse files
authored
Merge pull request #137 from wa5i/cli
Add interface: /internal/ui/mounts
2 parents 9eddcdc + 090c8c7 commit 96ca26d

12 files changed

Lines changed: 579 additions & 73 deletions

File tree

src/api/auth_token.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl TokenAuth<'_> {
5959

6060
pub fn create_with_role(&self, input: &TokenInput, role_name: &str) -> Result<HttpResponse, RvError> {
6161
let data = serde_json::to_value(input)?;
62-
self.request_write(&format!("/v1/auth/token/create/{}", role_name), data.as_object().cloned())
62+
self.request_write(format!("/v1/auth/token/create/{}", role_name), data.as_object().cloned())
6363
}
6464

6565
pub fn lookup(&self, token: &str) -> Result<HttpResponse, RvError> {

src/api/client.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,13 @@ impl Client {
156156
self
157157
}
158158

159-
pub fn request(&self, method: &str, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
159+
pub fn request<S: Into<String>>(
160+
&self,
161+
method: &str,
162+
path: S,
163+
data: Option<Map<String, Value>>,
164+
) -> Result<HttpResponse, RvError> {
165+
let path = path.into();
160166
let url = if path.starts_with('/') {
161167
format!("{}{}", self.address, path)
162168
} else {
@@ -199,27 +205,39 @@ impl Client {
199205
}
200206
}
201207

202-
pub fn request_list(&self, path: &str) -> Result<HttpResponse, RvError> {
208+
pub fn request_list<S: Into<String>>(&self, path: S) -> Result<HttpResponse, RvError> {
203209
self.request("LIST", path, None)
204210
}
205211

206-
pub fn request_read(&self, path: &str) -> Result<HttpResponse, RvError> {
212+
pub fn request_read<S: Into<String>>(&self, path: S) -> Result<HttpResponse, RvError> {
207213
self.request("GET", path, None)
208214
}
209215

210-
pub fn request_get(&self, path: &str) -> Result<HttpResponse, RvError> {
216+
pub fn request_get<S: Into<String>>(&self, path: S) -> Result<HttpResponse, RvError> {
211217
self.request("GET", path, None)
212218
}
213219

214-
pub fn request_write(&self, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
220+
pub fn request_write<S: Into<String>>(
221+
&self,
222+
path: S,
223+
data: Option<Map<String, Value>>,
224+
) -> Result<HttpResponse, RvError> {
215225
self.request("POST", path, data)
216226
}
217227

218-
pub fn request_put(&self, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
228+
pub fn request_put<S: Into<String>>(
229+
&self,
230+
path: S,
231+
data: Option<Map<String, Value>>,
232+
) -> Result<HttpResponse, RvError> {
219233
self.request("PUT", path, data)
220234
}
221235

222-
pub fn request_delete(&self, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
236+
pub fn request_delete<S: Into<String>>(
237+
&self,
238+
path: S,
239+
data: Option<Map<String, Value>>,
240+
) -> Result<HttpResponse, RvError> {
223241
self.request("DELETE", path, data)
224242
}
225243
}

src/api/logical.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ impl Client {
1818

1919
impl Logical<'_> {
2020
pub fn read(&self, path: &str) -> Result<HttpResponse, RvError> {
21-
self.request_read(&format!("/v1/{}", path))
21+
self.request_read(format!("/v1/{}", path))
2222
}
2323

2424
pub fn write(&self, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
25-
self.request_write(&format!("/v1/{}", path), data)
25+
self.request_write(format!("/v1/{}", path), data)
2626
}
2727

2828
pub fn list(&self, path: &str) -> Result<HttpResponse, RvError> {
29-
let mut ret = self.request_list(&format!("/v1/{}", path))?;
29+
let mut ret = self.request_list(format!("/v1/{}", path))?;
3030
if ret.response_status != 200 || ret.response_data.is_none() {
3131
return Ok(ret);
3232
}
@@ -38,6 +38,6 @@ impl Logical<'_> {
3838
}
3939

4040
pub fn delete(&self, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
41-
self.request_delete(&format!("/v1/{}", path), data)
41+
self.request_delete(format!("/v1/{}", path), data)
4242
}
4343
}

src/api/sys.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,20 @@ impl Sys<'_> {
111111

112112
pub fn enable_auth(&self, path: &str, input: &AuthInput) -> Result<HttpResponse, RvError> {
113113
let data = serde_json::to_value(input)?;
114-
self.request_write(&format!("/v1/sys/auth/{}", path), data.as_object().cloned())
114+
self.request_write(format!("/v1/sys/auth/{}", path), data.as_object().cloned())
115115
}
116116

117117
pub fn disable_auth(&self, path: &str) -> Result<HttpResponse, RvError> {
118-
self.request_delete(&format!("/v1/sys/auth/{}", path), None)
118+
self.request_delete(format!("/v1/sys/auth/{}", path), None)
119119
}
120120

121121
pub fn mount(&self, path: &str, input: &MountInput) -> Result<HttpResponse, RvError> {
122122
let data = serde_json::to_value(input)?;
123-
self.request_write(&format!("/v1/sys/mounts/{}", path), data.as_object().cloned())
123+
self.request_write(format!("/v1/sys/mounts/{}", path), data.as_object().cloned())
124124
}
125125

126126
pub fn unmount(&self, path: &str) -> Result<HttpResponse, RvError> {
127-
self.request_delete(&format!("/v1/sys/mounts/{}", path), None)
127+
self.request_delete(format!("/v1/sys/mounts/{}", path), None)
128128
}
129129

130130
pub fn remount(&self, from: &str, to: &str) -> Result<HttpResponse, RvError> {
@@ -145,18 +145,18 @@ impl Sys<'_> {
145145
}
146146

147147
pub fn read_policy(&self, name: &str) -> Result<HttpResponse, RvError> {
148-
self.request_read(&format!("/v1/sys/policies/acl/{}", name))
148+
self.request_read(format!("/v1/sys/policies/acl/{}", name))
149149
}
150150

151151
pub fn write_policy(&self, name: &str, policy: &str) -> Result<HttpResponse, RvError> {
152152
let data = json!({
153153
"policy": policy,
154154
});
155155

156-
self.request_write(&format!("/v1/sys/policies/acl/{}", name), data.as_object().cloned())
156+
self.request_write(format!("/v1/sys/policies/acl/{}", name), data.as_object().cloned())
157157
}
158158

159159
pub fn delete_policy(&self, name: &str) -> Result<HttpResponse, RvError> {
160-
self.request_delete(&format!("/v1/sys/policies/acl/{}", name), None)
160+
self.request_delete(format!("/v1/sys/policies/acl/{}", name), None)
161161
}
162162
}

src/cli/kv_util.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use serde_json::{Map, Value};
2+
3+
use crate::{
4+
api::{Client, HttpResponse},
5+
errors::RvError,
6+
rv_error_string,
7+
};
8+
9+
pub fn kv_read_request(client: &Client, path: &str, data: Option<Map<String, Value>>) -> Result<HttpResponse, RvError> {
10+
client.request("GET", format!("/v1/{}", path), data)
11+
}
12+
13+
pub fn kv_preflight_version_request(client: &Client, path: &str) -> Result<(String, u32), RvError> {
14+
let resp = client.request_read(format!("/v1/sys/internal/ui/mounts/{}", path))?;
15+
16+
if resp.response_status == 404 {
17+
// If we get a 404 we are using an older version of rusty_vault, default to version 1
18+
return Ok(("".to_string(), 1));
19+
}
20+
21+
let Some(data) = resp.response_data else {
22+
return Err(rv_error_string!("nil response from pre-flight request"));
23+
};
24+
25+
let path = data["path"].as_str().unwrap_or("");
26+
let version: u32 = if let Some(options) = data.get("options") {
27+
match options["version"].as_str().unwrap_or("") {
28+
"2" => 2,
29+
_ => 1,
30+
}
31+
} else {
32+
1
33+
};
34+
35+
Ok((path.to_string(), version))
36+
}
37+
38+
pub fn is_kv_v2(client: &Client, path: &str) -> Result<(String, bool), RvError> {
39+
let (mount_path, version) = kv_preflight_version_request(client, path)?;
40+
Ok((mount_path, version == 2))
41+
}

src/cli/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{cli::command::CommandExecutor, EXIT_CODE_INSUFFICIENT_PARAMS, VERSIO
88

99
pub mod command;
1010
pub mod config;
11+
pub mod kv_util;
1112
pub mod util;
1213

1314
#[derive(Parser)]

src/http/sys.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,29 @@ async fn sys_delete_policies_request_handler(
400400
handle_request(core, &mut r).await
401401
}
402402

403+
async fn sys_get_internal_ui_mounts_request_handler(
404+
req: HttpRequest,
405+
core: web::Data<Arc<RwLock<Core>>>,
406+
) -> Result<HttpResponse, RvError> {
407+
let mut r = request_auth(&req);
408+
r.path = "sys/internal/ui/mounts".to_string();
409+
r.operation = Operation::Read;
410+
411+
handle_request(core, &mut r).await
412+
}
413+
414+
async fn sys_get_internal_ui_mount_request_handler(
415+
req: HttpRequest,
416+
name: web::Path<String>,
417+
core: web::Data<Arc<RwLock<Core>>>,
418+
) -> Result<HttpResponse, RvError> {
419+
let mut r = request_auth(&req);
420+
r.path = "sys/internal/ui/mounts/".to_owned() + name.into_inner().as_str();
421+
r.operation = Operation::Read;
422+
423+
handle_request(core, &mut r).await
424+
}
425+
403426
pub fn init_sys_service(cfg: &mut web::ServiceConfig) {
404427
cfg.service(
405428
web::scope("/v1/sys")
@@ -452,6 +475,13 @@ pub fn init_sys_service(cfg: &mut web::ServiceConfig) {
452475
.route(web::get().to(sys_read_policies_request_handler))
453476
.route(web::post().to(sys_write_policies_request_handler))
454477
.route(web::delete().to(sys_delete_policies_request_handler)),
478+
)
479+
.service(
480+
web::resource("/internal/ui/mounts").route(web::get().to(sys_get_internal_ui_mounts_request_handler)),
481+
)
482+
.service(
483+
web::resource("/internal/ui/mounts/{name:.*}")
484+
.route(web::get().to(sys_get_internal_ui_mount_request_handler)),
455485
),
456486
);
457487
}

src/logical/request.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,32 @@ pub struct Request {
3636
}
3737

3838
impl Request {
39-
pub fn new(path: &str) -> Self {
40-
Self { path: path.to_string(), ..Default::default() }
39+
pub fn new<S: Into<String>>(path: S) -> Self {
40+
Self { path: path.into(), ..Default::default() }
4141
}
4242

43-
pub fn new_revoke_request(path: &str, secret: Option<SecretData>, data: Option<Map<String, Value>>) -> Self {
44-
Self { operation: Operation::Revoke, path: path.to_string(), secret, data, ..Default::default() }
43+
pub fn new_revoke_request<S: Into<String>>(
44+
path: S,
45+
secret: Option<SecretData>,
46+
data: Option<Map<String, Value>>,
47+
) -> Self {
48+
Self { operation: Operation::Revoke, path: path.into(), secret, data, ..Default::default() }
4549
}
4650

47-
pub fn new_renew_request(path: &str, secret: Option<SecretData>, data: Option<Map<String, Value>>) -> Self {
48-
Self { operation: Operation::Renew, path: path.to_string(), secret, data, ..Default::default() }
51+
pub fn new_renew_request<S: Into<String>>(
52+
path: S,
53+
secret: Option<SecretData>,
54+
data: Option<Map<String, Value>>,
55+
) -> Self {
56+
Self { operation: Operation::Renew, path: path.into(), secret, data, ..Default::default() }
4957
}
5058

51-
pub fn new_renew_auth_request(path: &str, auth: Option<Auth>, data: Option<Map<String, Value>>) -> Self {
52-
Self { operation: Operation::Renew, path: path.to_string(), auth, data, ..Default::default() }
59+
pub fn new_renew_auth_request<S: Into<String>>(
60+
path: S,
61+
auth: Option<Auth>,
62+
data: Option<Map<String, Value>>,
63+
) -> Self {
64+
Self { operation: Operation::Renew, path: path.into(), auth, data, ..Default::default() }
5365
}
5466

5567
pub fn bind_handler(&mut self, handler: Arc<dyn Handler>) {

src/modules/auth/expiration.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ mod mod_expiration_tests {
12041204
let paths = ["prod/aws/foo", "prod/aws/sub/bar", "prod/aws/zip"];
12051205

12061206
for path in paths.iter() {
1207-
let mut req = Request::new(path);
1207+
let mut req = Request::new(*path);
12081208
req.client_token = "foobar".into();
12091209
let mut resp = Response {
12101210
secret: Some(SecretData {
@@ -1267,7 +1267,7 @@ mod mod_expiration_tests {
12671267
let paths = ["prod/aws/foo", "prod/aws/sub/bar", "prod/aws/zip"];
12681268

12691269
for path in paths.iter() {
1270-
let mut req = Request::new(path);
1270+
let mut req = Request::new(*path);
12711271
req.client_token = "foobar".into();
12721272
let mut resp = Response {
12731273
secret: Some(SecretData {

0 commit comments

Comments
 (0)