+ add post_meta
+ add destroy_secret
This commit is contained in:
parent
a6de2133fd
commit
620df86c06
3 changed files with 168 additions and 18 deletions
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
var client *vault.Client
|
||||
var ctx context.Context
|
||||
|
||||
// Apparently used as a default if mountpath is an empty string (client library)
|
||||
var mountpath = "/kv-v2"
|
||||
var mountpath2 = "/some"
|
||||
|
|
@ -106,14 +107,54 @@ func TestDeleteSecret(t *testing.T) {
|
|||
|
||||
func TestReadSecret(t *testing.T) {
|
||||
_, err := client.Secrets.KvV2Read(ctx, "bar")
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("kv2: Failed to read secret:\n\t", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadSecret2(t *testing.T) {
|
||||
_, err := client.Secrets.KvV2Read(ctx, "ba")
|
||||
func TestReadMeta(t *testing.T) {
|
||||
_, err := client.Secrets.KvV2ReadMetadata(ctx, "bar")
|
||||
if err != nil {
|
||||
log.Fatal("kv2: Failed to read secret:\n\t", err)
|
||||
log.Fatal("kv2: Failed to read metadata:\n\t", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteAndReadMeta(t *testing.T) {
|
||||
meta := schema.KvV2WriteMetadataRequest{
|
||||
MaxVersions: 5,
|
||||
CasRequired: false,
|
||||
DeleteVersionAfter: "3h25m19s",
|
||||
CustomMetadata: map[string]interface{}{
|
||||
"foo": "abc",
|
||||
"bar": "123",
|
||||
"baz": "5c07d823-3810-48f6-a147-4c06b5219e84",
|
||||
},
|
||||
}
|
||||
_, err := client.Secrets.KvV2WriteMetadata(ctx, "newMeta", meta)
|
||||
if err != nil {
|
||||
log.Fatal("kv2: Failed to write metadata:\n\t", err)
|
||||
}
|
||||
|
||||
// read the metadata
|
||||
_, err2 := client.Secrets.KvV2ReadMetadata(ctx, "newMeta")
|
||||
if err2 != nil {
|
||||
log.Fatal("kv2: Failed to read metadata:\n\t", err)
|
||||
}
|
||||
}
|
||||
|
||||
// does NOT revert destruction
|
||||
func TestDestroySecret(t *testing.T) {
|
||||
_, err := client.Secrets.KvV2DestroyVersions(ctx, "bar", schema.KvV2DestroyVersionsRequest{Versions: []int32{1}})
|
||||
if err != nil {
|
||||
log.Fatal("kv2: Failed to destroy secret:\n\t", err)
|
||||
}
|
||||
}
|
||||
|
||||
// does NOT revert destruction
|
||||
func TestDestroySecret2(t *testing.T) {
|
||||
_, err := client.Secrets.KvV2DestroyVersions(ctx, "bar", schema.KvV2DestroyVersionsRequest{Versions: []int32{1, 2}})
|
||||
if err != nil {
|
||||
log.Fatal("kv2: Failed to destroy secret:\n\t", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@ pub mod http_structs;
|
|||
// #[cfg(test)]
|
||||
// mod tests;
|
||||
|
||||
use crate::{
|
||||
engines::kv::{self, http_structs::*},
|
||||
storage::DatabaseDriver,
|
||||
};
|
||||
use crate::{engines::kv::http_structs::*, storage::DatabaseDriver};
|
||||
use axum::{
|
||||
extract::{self, Path, State},
|
||||
http::StatusCode,
|
||||
|
|
@ -24,7 +21,7 @@ use chrono::{DateTime, Utc};
|
|||
use db_structs::*;
|
||||
use log::{error, info};
|
||||
use serde_json;
|
||||
use sqlx::{error, Row};
|
||||
use sqlx::{Row, Sqlite};
|
||||
use std::{collections::HashMap, convert::Infallible};
|
||||
|
||||
pub fn kv_router(pool: DatabaseDriver) -> Router {
|
||||
|
|
@ -182,8 +179,48 @@ async fn delete_path() -> &'static str {
|
|||
todo!("not implemented")
|
||||
}
|
||||
|
||||
async fn destroy_path() -> &'static str {
|
||||
todo!("not implemented")
|
||||
async fn destroy_path(
|
||||
State(pool): State<DatabaseDriver>,
|
||||
Path(kv_path): Path<String>,
|
||||
Json(body): Json<KvSecretDestrReq>,
|
||||
) -> Result<impl IntoResponse, Infallible> {
|
||||
let versions = body.versions;
|
||||
|
||||
for ver in versions {
|
||||
let res_wrapper = sqlx::query::<Sqlite>(
|
||||
"DELETE FROM secret_versions where secret_path = $1 AND version_number = $2",
|
||||
)
|
||||
.bind(&kv_path)
|
||||
.bind(ver)
|
||||
.execute(&pool)
|
||||
.await;
|
||||
|
||||
match res_wrapper {
|
||||
Ok(result) => {
|
||||
if result.rows_affected() == 0 {
|
||||
log::debug!(
|
||||
"No rows were deleted for version {} at path {}",
|
||||
ver,
|
||||
kv_path
|
||||
);
|
||||
} else {
|
||||
log::debug!("Deleted version {} at path {}", ver, kv_path);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"Failed to delete version {} at path {}: {}",
|
||||
ver,
|
||||
kv_path,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if all are gone
|
||||
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
async fn get_meta(
|
||||
|
|
@ -278,14 +315,59 @@ async fn get_meta(
|
|||
Ok((StatusCode::OK, Json(metadata_res)).into_response())
|
||||
}
|
||||
|
||||
// currently only writes the metadata - No case if already exists
|
||||
async fn post_meta(
|
||||
State(pool): State<DatabaseDriver>,
|
||||
Path((mount_path, kv_path)): Path<(String, String)>,
|
||||
body: String,
|
||||
) -> &'static str {
|
||||
// let mut body_json = body_to_json(body);
|
||||
// let meta_data: SecretMeta = Default::default();
|
||||
todo!("not implemented")
|
||||
Path(kv_path): Path<String>,
|
||||
Json(body): Json<KvMetaReq>,
|
||||
// extract::Json(body): extract::Json<http_structs::KvMetaReq>,
|
||||
) -> Result<impl IntoResponse, Infallible> {
|
||||
let now = Utc::now();
|
||||
let custom_metadata: String = match serde_json::to_string(&body.custom_metadata) {
|
||||
Ok(data) => data,
|
||||
Err(_) => {
|
||||
log::error!(
|
||||
"could not serialize custom_metadata: {:?}\ndropping data",
|
||||
body.custom_metadata
|
||||
);
|
||||
String::new()
|
||||
}
|
||||
};
|
||||
|
||||
let new_metadata = DbSecretMeta {
|
||||
cas_required: body.cas_required.unwrap_or(false),
|
||||
secret_path: kv_path,
|
||||
created_time: now,
|
||||
delete_version_after: Some("30d".to_string()),
|
||||
max_versions: body.max_versions,
|
||||
updated_time: now,
|
||||
|
||||
custom_data: Some(custom_metadata),
|
||||
};
|
||||
|
||||
match sqlx::query("INSERT INTO metadata (cas_required, secret_path, created_time, delete_version_after, max_versions, updated_time, custom_data) VALUES ($1, $2, $3, $4, $5, $6, $7)")
|
||||
.bind(new_metadata.cas_required)
|
||||
.bind(new_metadata.secret_path)
|
||||
.bind(new_metadata.created_time)
|
||||
.bind(new_metadata.delete_version_after.unwrap())
|
||||
.bind(new_metadata.max_versions)
|
||||
.bind(new_metadata.updated_time)
|
||||
.bind(new_metadata.custom_data.unwrap())
|
||||
.execute(&pool)
|
||||
.await
|
||||
{
|
||||
Ok(result) => {
|
||||
info!("{:?}", result);
|
||||
if result.rows_affected() == 0 {
|
||||
log::error!("Failed to insert metadata");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{:?}", e);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
async fn delete_meta() -> &'static str {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ impl ErrorStruct {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
/// HTTP Request to destroy secret versions
|
||||
pub struct KvSecretDestrReq {
|
||||
pub versions: Vec<i64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
/// HTTP Response to Reading a Secret metadata
|
||||
/// Container of [`KvMetaResData`]
|
||||
|
|
@ -105,8 +111,29 @@ pub struct KvMetaResData {
|
|||
pub max_versions: i64,
|
||||
pub oldest_version: i64,
|
||||
pub updated_time: DateTime<Utc>,
|
||||
// pub custom_metadata: Option<String>, // TODO as hashmap
|
||||
pub custom_metadata: Option<HashMap<String, String>>,
|
||||
pub versions: HashMap<i64, KvMetaResVersionData>,
|
||||
// the key to a version is the version number
|
||||
}
|
||||
|
||||
// Example
|
||||
// {
|
||||
// "max_versions": 5,
|
||||
// "cas_required": false,
|
||||
// "delete_version_after": "3h25m19s",
|
||||
// "custom_metadata": {
|
||||
// "foo": "abc",
|
||||
// "bar": "123",
|
||||
// "baz": "5c07d823-3810-48f6-a147-4c06b5219e84"
|
||||
// }
|
||||
// }
|
||||
#[derive(Serialize, Debug, Deserialize)]
|
||||
/// HTTP Request to post metadatas
|
||||
pub struct KvMetaReq {
|
||||
pub cas_required: Option<bool>,
|
||||
// pub cas_required: bool,
|
||||
pub delete_version_after: Option<String>,
|
||||
pub max_versions: i64,
|
||||
// pub updated_time: Option<DateTime<Utc>>,
|
||||
pub custom_metadata: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue