Merge branch 'dev' of https://github.com/C0ffeeCode/rvault into dev
This commit is contained in:
commit
acb538eaea
8 changed files with 73 additions and 65 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,9 +2,11 @@
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
.env
|
||||||
|
|
||||||
*.pdf
|
*.pdf
|
||||||
target/
|
target/
|
||||||
go_client/openapi.json
|
go_client/openapi.json
|
||||||
crates/storage-sled/sled_db
|
crates/storage-sled/sled_db
|
||||||
test.db
|
test.db
|
||||||
|
src/storage/database.db
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ RUN go mod download
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
# RUN go build -o /app
|
# RUN go build -o /app
|
||||||
|
RUN go build
|
||||||
CMD go test tests/*
|
CMD go test tests/*
|
||||||
|
|
||||||
# FROM docker.io/library/alpine:3.19
|
# FROM docker.io/library/alpine:3.19
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ import (
|
||||||
|
|
||||||
var client *vault.Client
|
var client *vault.Client
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var mountpath = ""
|
// Apparently used as a default if mountpath is an empty string (client library)
|
||||||
|
var mountpath = "/kv-v2"
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,5 @@ CREATE TABLE secret_engines (
|
||||||
mount_point TEXT PRIMARY KEY NOT NULL,
|
mount_point TEXT PRIMARY KEY NOT NULL,
|
||||||
engine_type TEXT NOT NULL
|
engine_type TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
INSERT INTO secret_engines (mount_point, engine_type) VALUES ('/kv-v2', 'kv');
|
||||||
|
|
|
||||||
28
migrations/20240501152243_KvSecret.sql
Normal file
28
migrations/20240501152243_KvSecret.sql
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
-- Add migration script here
|
||||||
|
|
||||||
|
CREATE TABLE metadata (
|
||||||
|
secret_path TEXT PRIMARY KEY NOT NULL,
|
||||||
|
|
||||||
|
cas_required INTEGER NOT NULL, -- no bool datatype in sqlite
|
||||||
|
created_time TIMESTAMP NOT NULL,
|
||||||
|
delete_version_after TEXT, -- Maybe NOT NULL
|
||||||
|
max_versions INTEGER NOT NULL,
|
||||||
|
-- current_version INTEGER NOT NULL,
|
||||||
|
-- oldest_version INTEGER NOT NULL,
|
||||||
|
updated_time TIMESTAMP NOT NULL,
|
||||||
|
custom_data TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE secret_versions (
|
||||||
|
secret_data TEXT NOT NULL,
|
||||||
|
|
||||||
|
created_time TIMESTAMP NOT NULL,
|
||||||
|
deletion_time TIMESTAMP,
|
||||||
|
|
||||||
|
version_number INTEGER NOT NULL DEFAULT 0,
|
||||||
|
secret_path TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (secret_path, version_number),
|
||||||
|
FOREIGN KEY (secret_path) REFERENCES metadata(secret_path)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_secret_versions_secret_path ON secret_versions (secret_path);
|
||||||
|
|
@ -1,77 +1,46 @@
|
||||||
pub mod kv;
|
pub mod kv;
|
||||||
|
|
||||||
use crate::engines::kv::logic::body_to_json;
|
|
||||||
use crate::engines::kv::structs::KvSecret;
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, Request},
|
body::Body,
|
||||||
http::StatusCode,
|
extract::{Request, State},
|
||||||
middleware::{self, Next},
|
|
||||||
response::Response,
|
response::Response,
|
||||||
routing::*,
|
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use log::*;
|
use log::*;
|
||||||
use sqlx::{Any, Pool};
|
use sqlx::{Any, Pool};
|
||||||
|
|
||||||
pub fn secrets_router(pool: Pool<Any>) -> Router<Pool<Any>> {
|
pub fn secrets_router(pool: Pool<Any>) -> Router<Pool<Any>> {
|
||||||
// Router::new().layer(map_request(handler))
|
Router::new().fallback(map_mount_points).with_state(pool)
|
||||||
|
|
||||||
Router::new()
|
|
||||||
.route("/:mount_path/data/:kv_path", post(baz))
|
|
||||||
.with_state(pool)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Routing handler for path "/v1/kv-v2/data/foo"
|
async fn map_mount_points(State(_pool): State<Pool<Any>>, req: Request) -> Response<Body> {
|
||||||
/// expects payload as JSON, prints payload into struct
|
// let mount_path = mount_path.trim_start_matches('/');
|
||||||
|
// debug!("Mount path: {}", mount_path);
|
||||||
|
debug!("Mount path: {:?}", req);
|
||||||
|
|
||||||
async fn baz(Path(mount_path): Path<String>, Path(kv_path): Path<String>, body: String) -> String {
|
let mut mount_path: Vec<&str> = req.uri().path().split("/").collect();
|
||||||
let mut body_json = body_to_json(body);
|
|
||||||
|
|
||||||
// TODO: If version field provided during a read, the value at the version number will be returned
|
// let a = sqlx::query!("SELECT * FROM secret_engines WHERE path = $1", mount_path.join("/"))
|
||||||
let secret: KvSecret = KvSecret {
|
// .fetch_one(&pool)
|
||||||
data: body_json.to_string(),
|
// .await
|
||||||
// content: body_json["data"]["password1"].take().to_string(),
|
// .expect("Failed to fetch secret engine");
|
||||||
version: body_json["data"]["version"].take().as_i64(),
|
|
||||||
};
|
let tada = vec!["a/b/c/d".to_string(), "/a/b/c".to_string(), "/kv-v2".into()];
|
||||||
log::debug!(
|
|
||||||
"Secret: {}, Content: {}, Version: {:?}, path: {}",
|
// Find longest matching existing mount path for the request
|
||||||
kv_path,
|
for _ in 1..mount_path.len() {
|
||||||
secret.data,
|
if tada.contains(&mount_path.join("/")) {
|
||||||
secret.version,
|
trace!(
|
||||||
mount_path,
|
"Mount path {} found for route request: {}",
|
||||||
|
mount_path.join("/"),
|
||||||
|
req.uri().path()
|
||||||
);
|
);
|
||||||
String::from("RoutingTest baz successful")
|
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
mount_path.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// async fn handler(Host(hostname): Host, request: Request<Body>) -> &'static str {
|
return Response::new(Body::from(format!("Mount path:")));
|
||||||
// TODO: Find a solution for this mess
|
}
|
||||||
// async fn handler(request: Request<Body>) -> Result<Request<Body>, StatusCode> {
|
|
||||||
// // let path: Vec<&str> = request.uri().path().split('/').clone().collect();
|
|
||||||
// // log::info!("path, {:?}", path[1]);
|
|
||||||
|
|
||||||
// let root = service_fn(|req: Request<String>| async move {
|
|
||||||
// let res = Response::new("Hello, World!".to_string());
|
|
||||||
// Ok::<_, Infallible>(res)
|
|
||||||
// });
|
|
||||||
// let root = BoxService::new(root);
|
|
||||||
|
|
||||||
// let mut routes = vec!["/abc", "/def"];
|
|
||||||
// routes.sort_unstable_by(|a, b| a.len().cmp(&b.len()));
|
|
||||||
|
|
||||||
// let mut app = Router::new();
|
|
||||||
// app.as_service().call(request).await.unwrap();
|
|
||||||
|
|
||||||
// // match path[1] {
|
|
||||||
// // "test" => {
|
|
||||||
// // log::info!("test route");
|
|
||||||
// // // TODO: Nest another Router here
|
|
||||||
// // return Ok(Request::new(Body::empty()));
|
|
||||||
// // }
|
|
||||||
// // _ => {
|
|
||||||
// // log::info!("default");
|
|
||||||
// // return Err(StatusCode::NOT_FOUND);
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// Err(StatusCode::IM_A_TEAPOT)
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::HashMap, hash::Hash, vec};
|
use std::{collections::HashMap, vec};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct KvSecret {
|
pub struct KvSecret {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ pub async fn create_pool(db_url: String) -> AnyPool {
|
||||||
sqlx::any::install_default_drivers();
|
sqlx::any::install_default_drivers();
|
||||||
|
|
||||||
// Create SQLite database file if it does not exist
|
// Create SQLite database file if it does not exist
|
||||||
if db_url.starts_with("sqlite:") {
|
if db_url.starts_with("sqlite:") && db_url != ("sqlite::memory:") {
|
||||||
let path = db_url.replace("sqlite:", "");
|
let path = db_url.replace("sqlite:", "");
|
||||||
if !Path::new(&path).exists() {
|
if !Path::new(&path).exists() {
|
||||||
warn!("Sqlite database does not exist, creating file {}", path);
|
warn!("Sqlite database does not exist, creating file {}", path);
|
||||||
|
|
@ -23,5 +23,10 @@ pub async fn create_pool(db_url: String) -> AnyPool {
|
||||||
.await
|
.await
|
||||||
.expect(&db_url);
|
.expect(&db_url);
|
||||||
|
|
||||||
|
sqlx::migrate!()
|
||||||
|
.run(&pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to apply migrations");
|
||||||
|
|
||||||
pool
|
pool
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue