Skip to content

Commit

Permalink
Add kv1::list_with_http_get and kv2::list_with_http_get methods
Browse files Browse the repository at this point in the history
  • Loading branch information
orf committed Nov 20, 2024
1 parent 4c48122 commit a0b89f8
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 5 deletions.
25 changes: 25 additions & 0 deletions src/api/kv1/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,31 @@ pub struct ListSecretRequest {
pub path: String,
}

/// ## List secret keys with HTTP GET
/// This endpoint list secrets at given location
/// Some servers and middleware may not support custom HTTP methods such as `LIST`. This
/// endpoint provides an alternative way to list secrets using HTTP GET.
///
/// * Path: {self.mount}/{self.path}?list=true
/// * Method: GET
/// * Response: ListSecretResponse
/// * Reference: <https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v1#list-secrets>
#[derive(Builder, Debug, Endpoint)]
#[endpoint(
path = "{self.mount}/{self.path}",
builder = "true",
response = "ListSecretResponse"
)]
#[builder(setter(into))]
pub struct ListSecretUsingGetRequest {
#[endpoint(skip)]
pub mount: String,
#[endpoint(skip)]
pub path: String,
#[endpoint(query)]
pub list: bool,
}

/// ## Delete secret
/// This endpoint delete a secret at given location
///
Expand Down
25 changes: 25 additions & 0 deletions src/api/kv2/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,31 @@ pub struct ListSecretsRequest {
pub path: String,
}

/// ## List Secrets with HTTP GET
/// This endpoint returns a list of key names at the specified location.
/// Some servers and middleware may not support custom HTTP methods such as `LIST`. This
/// endpoint provides an alternative way to list secrets using HTTP GET.
///
/// * Path: {self.mount}/metadata/{self.path}?list=true
/// * Method: GET
/// * Response: N/A
/// * Reference: <https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v2#list-secrets>
#[derive(Builder, Debug, Endpoint)]
#[endpoint(
path = "{self.mount}/metadata/{self.path}",
response = "ListSecretsResponse",
builder = "true"
)]
#[builder(setter(into))]
pub struct ListSecretsUsingGetRequest {
#[endpoint(skip)]
pub mount: String,
#[endpoint(skip)]
pub path: String,
#[endpoint(query)]
pub list: bool,
}

/// ## Read Secret Metadata
/// This endpoint retrieves the metadata and versions for the secret at the
/// specified path.
Expand Down
21 changes: 20 additions & 1 deletion src/kv1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::{
self,
kv1::{
requests::{
DeleteSecretRequest, GetSecretRequest, ListSecretRequest, SetSecretRequest,
DeleteSecretRequest, GetSecretRequest, ListSecretRequest,
ListSecretUsingGetRequest, SetSecretRequest,
},
responses::{GetSecretResponse, ListSecretResponse},
},
Expand Down Expand Up @@ -95,6 +96,24 @@ pub async fn list(
api::exec_with_no_result(client, endpoint).await
}

/// List secret keys at given location, using the HTTP GET method, returning raw server response
///
/// See [ListSecretUsingGetRequest]
pub async fn list_with_http_get(
client: &impl Client,
mount: &str,
path: &str,
) -> Result<ListSecretResponse, ClientError> {
let endpoint = ListSecretUsingGetRequest::builder()
.mount(mount)
.path(path)
.list(true)
.build()
.unwrap();

api::exec_with_no_result(client, endpoint).await
}

/// Delete secret at given location
///
/// See [DeleteSecretRequest]
Expand Down
23 changes: 20 additions & 3 deletions src/kv2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::{
requests::{
DeleteLatestSecretVersionRequest, DeleteSecretMetadataRequest,
DeleteSecretVersionsRequest, DestroySecretVersionsRequest, ListSecretsRequest,
ReadSecretMetadataRequest, ReadSecretRequest, SetSecretMetadataRequest,
SetSecretMetadataRequestBuilder, SetSecretRequest, SetSecretRequestOptions,
UndeleteSecretVersionsRequest,
ListSecretsUsingGetRequest, ReadSecretMetadataRequest, ReadSecretRequest,
SetSecretMetadataRequest, SetSecretMetadataRequestBuilder, SetSecretRequest,
SetSecretRequestOptions, UndeleteSecretVersionsRequest,
},
responses::{ReadSecretMetadataResponse, SecretVersionMetadata},
},
Expand Down Expand Up @@ -101,6 +101,23 @@ pub async fn list(
Ok(api::exec_with_result(client, endpoint).await?.keys)
}

/// Lists all secret keys at the given path
///
/// See [ListSecretsUsingGetRequest]
pub async fn list_with_http_get(
client: &impl Client,
mount: &str,
path: &str,
) -> Result<Vec<String>, ClientError> {
let endpoint = ListSecretsUsingGetRequest::builder()
.mount(mount)
.path(path)
.list(true)
.build()
.unwrap();
Ok(api::exec_with_result(client, endpoint).await?.keys)
}

/// Reads the value of the secret at the given path
///
/// See [ReadSecretRequest]
Expand Down
4 changes: 3 additions & 1 deletion vaultrs-tests/tests/api_tests/kv1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ async fn test_kv1() {

// List secret keys
let list_secret = kv1::list(client, mount, "mysecret").await.unwrap();

println!("{:?}", list_secret);
assert_eq!(list_secret.data.keys, vec!["foo"]);

let list_secret = kv1::list_with_http_get(client, mount, "mysecret").await.unwrap();
println!("{:?}", list_secret);
assert_eq!(list_secret.data.keys, vec!["foo"]);

// Delete secret and read again and expect 404 to check deletion
Expand Down
9 changes: 9 additions & 0 deletions vaultrs-tests/tests/api_tests/kv2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ async fn test_kv2_url_encoding(client: &impl Client) {
assert_eq!(secrets.len(), 1);
assert_eq!(secrets.first().unwrap(), "password name with whitespace");

let secrets = kv2::list_with_http_get(client, path, "path/to/some secret/")
.await
.unwrap();
assert_eq!(secrets.len(), 1);
assert_eq!(secrets.first().unwrap(), "password name with whitespace");

let res: Result<TestSecret, _> = kv2::read(client, path, name).await;
assert!(res.is_ok());
assert_eq!(res.unwrap().key, endpoint.secret.key);
Expand Down Expand Up @@ -112,6 +118,9 @@ async fn test_list(client: &impl Client, endpoint: &SecretEndpoint) {
let res = kv2::list(client, endpoint.path.as_str(), "").await;
assert!(res.is_ok());
assert!(!res.unwrap().is_empty());
let res = kv2::list_with_http_get(client, endpoint.path.as_str(), "").await;
assert!(res.is_ok());
assert!(!res.unwrap().is_empty());
}

async fn test_read(client: &impl Client, endpoint: &SecretEndpoint) {
Expand Down

0 comments on commit a0b89f8

Please sign in to comment.