added database stuff

added clap arguments
added the gen_or_get_key func in lib
git ignore for .env
migrations
This commit is contained in:
2026-07-13 17:41:29 -05:00
parent 04c57f15f8
commit c64ed1be4e
15 changed files with 527 additions and 5 deletions
+4
View File
@@ -10,3 +10,7 @@ devenv.local.yaml
# pre-commit # pre-commit
.pre-commit-config.yaml .pre-commit-config.yaml
# Environment Variables
.env*
!.env.example
Generated
+370 -1
View File
@@ -32,6 +32,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "1.0.0" version = "1.0.0"
@@ -309,6 +318,16 @@ dependencies = [
"cipher 0.4.4", "cipher 0.4.4",
] ]
[[package]]
name = "cc"
version = "1.2.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.4" version = "1.0.4"
@@ -339,6 +358,19 @@ dependencies = [
"poly1305", "poly1305",
] ]
[[package]]
name = "chrono"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-link",
]
[[package]] [[package]]
name = "cipher" name = "cipher"
version = "0.4.4" version = "0.4.4"
@@ -404,11 +436,17 @@ checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
name = "cli" name = "cli"
version = "1.0.0" version = "1.0.0"
dependencies = [ dependencies = [
"chrono",
"clap", "clap",
"colored", "colored",
"crypto",
"diesel",
"dotenvy",
"git-version", "git-version",
"hex",
"keyring", "keyring",
"tokio", "tokio",
"uuid",
] ]
[[package]] [[package]]
@@ -519,6 +557,83 @@ dependencies = [
"cmov", "cmov",
] ]
[[package]]
name = "darling"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deranged"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
[[package]]
name = "diesel"
version = "2.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54d1f576cd3a3460f212a4615fd12ce1b6303c095b79a44449ffbe627753dc1"
dependencies = [
"chrono",
"diesel_derives",
"downcast-rs",
"libsqlite3-sys",
"sqlite-wasm-rs",
"time",
]
[[package]]
name = "diesel_derives"
version = "2.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1817b7f4279b947fc4cafddec12b0e5f8727141706561ce3ac94a60bddd1cf5"
dependencies = [
"diesel_table_macro_syntax",
"dsl_auto_type",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diesel_table_macro_syntax"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c"
dependencies = [
"syn",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
@@ -530,6 +645,38 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "downcast-rs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
[[package]]
name = "dsl_auto_type"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e"
dependencies = [
"darling",
"either",
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
[[package]] [[package]]
name = "endi" name = "endi"
version = "1.1.1" version = "1.1.1"
@@ -600,6 +747,24 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.32" version = "0.3.32"
@@ -708,6 +873,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"foldhash",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.17.1" version = "0.17.1"
@@ -759,6 +933,36 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.14.0" version = "2.14.0"
@@ -766,7 +970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown 0.17.1",
] ]
[[package]] [[package]]
@@ -832,6 +1036,16 @@ version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libsqlite3-sys"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.12.1" version = "0.12.1"
@@ -912,6 +1126,12 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "num-conv"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.46" version = "0.1.46"
@@ -1019,6 +1239,12 @@ dependencies = [
"futures-io", "futures-io",
] ]
[[package]]
name = "pkg-config"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]] [[package]]
name = "polling" name = "polling"
version = "3.11.0" version = "3.11.0"
@@ -1043,6 +1269,12 @@ dependencies = [
"universal-hash", "universal-hash",
] ]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.5.0" version = "3.5.0"
@@ -1131,6 +1363,16 @@ version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "rsqlite-vfs"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c"
dependencies = [
"hashbrown 0.16.1",
"thiserror",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "1.1.4" version = "1.1.4"
@@ -1250,6 +1492,12 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "shlex"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.8" version = "1.4.8"
@@ -1282,6 +1530,18 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "sqlite-wasm-rs"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75"
dependencies = [
"cc",
"js-sys",
"rsqlite-vfs",
"wasm-bindgen",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@@ -1318,6 +1578,56 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "thiserror"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50"
dependencies = [
"deranged",
"num-conv",
"powerfmt",
"serde_core",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "time-macros"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f"
dependencies = [
"num-conv",
"time-core",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.52.3" version = "1.52.3"
@@ -1457,6 +1767,12 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.5" version = "0.9.5"
@@ -1514,6 +1830,41 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "windows-link" name = "windows-link"
version = "0.2.1" version = "0.2.1"
@@ -1533,6 +1884,24 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.61.2" version = "0.61.2"
+12 -2
View File
@@ -7,8 +7,18 @@ description = "An opensource secrets management and distribution platform"
license = "GLP-3.0" license = "GLP-3.0"
[dependencies] [dependencies]
tokio = { version = "1.52.3", features = ["full"] } diesel = { version = "2.2.0", features = [
"sqlite",
"returning_clauses_for_sqlite_3_35",
"chrono",
] }
clap = { version = "4.6.1", features = ["derive", "cargo"] } clap = { version = "4.6.1", features = ["derive", "cargo"] }
tokio = { version = "1.52.3", features = ["full"] }
crypto = { path = "../crypto" }
git-version = "0.3"
keyring = "4.1.4" keyring = "4.1.4"
colored = "3.1.1" colored = "3.1.1"
git-version = "0.3" chrono = "0.4.45"
dotenvy = "0.15"
uuid = "1.23.5"
hex = "0.4"
+9
View File
@@ -0,0 +1,9 @@
# For documentation on how to configure this file,
# see https://diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/db/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
[migrations_directory]
dir = "migrations"
Binary file not shown.
View File
View File
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS secrets;
DROP TABLE IF EXISTS projects;
@@ -0,0 +1,19 @@
CREATE TABLE projects (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE secrets (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
project_id TEXT NOT NULL,
config TEXT NOT NULL,
secret BLOB NOT NULL,
nonce BLOB NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
UNIQUE (project_id, config, name)
);
+14
View File
@@ -0,0 +1,14 @@
use diesel::prelude::*;
use dotenvy::dotenv;
use std::env;
pub mod models;
pub mod schema;
pub fn establish_connection() -> SqliteConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
SqliteConnection::establish(&database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}
+25
View File
@@ -0,0 +1,25 @@
use crate::db::schema::{projects, secrets};
use chrono::NaiveDateTime;
use diesel::prelude::*;
#[derive(Debug, Queryable, Selectable)]
#[diesel(table_name = projects)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct Project {
pub id: String,
pub name: String,
pub created_at: NaiveDateTime,
}
#[derive(Debug, Queryable, Selectable)]
#[diesel(table_name = secrets)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct Secret {
pub id: String,
pub name: String,
pub project_id: String,
pub config: String,
pub secret: Vec<u8>,
pub nonce: Vec<u8>,
pub created_at: NaiveDateTime,
}
+25
View File
@@ -0,0 +1,25 @@
// @generated automatically by Diesel CLI.
diesel::table! {
projects (id) {
id -> Text,
name -> Text,
created_at -> Timestamp,
}
}
diesel::table! {
secrets (id) {
id -> Text,
name -> Text,
project_id -> Text,
config -> Text,
secret -> Binary,
nonce -> Binary,
created_at -> Timestamp,
}
}
diesel::joinable!(secrets -> projects (project_id));
diesel::allow_tables_to_appear_in_same_query!(projects, secrets,);
+39
View File
@@ -1,4 +1,7 @@
use clap::{Args, Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
use keyring::Entry;
use std::error::Error;
mod db;
#[derive(Parser)] #[derive(Parser)]
#[clap( #[clap(
@@ -54,3 +57,39 @@ pub enum ConfigCommands {
Create { project: String, name: String }, Create { project: String, name: String },
Delete { project: String, name: String }, Delete { project: String, name: String },
} }
pub fn gen_or_get_key() -> Result<crypto::Key, Box<dyn Error>> {
let entry = Entry::new("harbor", "encryption-key")?;
match entry.get_password() {
Ok(hex_string) => {
let key_bytes = hex::decode(hex_string)?;
if key_bytes.len() != 32 {
return Err("Retrieved key length is invalid (must be 32 bytes)".into());
}
Ok(key_bytes
.as_slice()
.try_into()
.map_err(|_| "Invalid key length")?)
}
Err(err) => {
if is_key_not_found(&err) {
let key = crypto::helper::gen_key();
let hex_string = hex::encode(key.as_slice());
entry.set_password(&hex_string)?;
Ok(key)
} else {
Err(Box::new(err))
}
}
}
}
fn is_key_not_found(err: &keyring::Error) -> bool {
matches!(err, keyring::Error::NoEntry)
}
+5 -2
View File
@@ -1,11 +1,14 @@
use chacha20poly1305::{ use chacha20poly1305::{
ChaCha20Poly1305, Key, Nonce, ChaCha20Poly1305,
aead::{Aead, Generate, KeyInit}, aead::{Aead, Generate, KeyInit},
}; };
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
mod helper { pub type Key = chacha20poly1305::Key;
pub type Nonce = chacha20poly1305::Nonce;
pub mod helper {
use super::{Generate, Key, Nonce}; use super::{Generate, Key, Nonce};
pub fn gen_nonce() -> Nonce { pub fn gen_nonce() -> Nonce {
Nonce::generate() Nonce::generate()
+3
View File
@@ -9,6 +9,7 @@
prettier prettier
nixfmt nixfmt
clippy clippy
sqlite
]; ];
languages.rust = { languages.rust = {
@@ -23,6 +24,8 @@
]; ];
}; };
dotenv.enable = true;
enterTest = '' enterTest = ''
cargo test cargo test
''; '';