This commit is contained in:
someone 2024-05-02 09:33:34 +02:00
commit acb538eaea
8 changed files with 73 additions and 65 deletions

2
.gitignore vendored
View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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');

View 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);

View file

@ -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("/"),
String::from("RoutingTest baz successful") req.uri().path()
);
break;
} else {
mount_path.pop();
}
}
return Response::new(Body::from(format!("Mount path:")));
} }
// async fn handler(Host(hostname): Host, request: Request<Body>) -> &'static str {
// 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)
// }

View file

@ -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 {

View file

@ -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
} }