feat: hash master key via sha2, add checks for secrets.json and update db
All checks were successful
Deployment Pipeline / deploy (push) Successful in 32s
All checks were successful
Deployment Pipeline / deploy (push) Successful in 32s
This commit is contained in:
49
src/main.rs
49
src/main.rs
@@ -1,5 +1,12 @@
|
||||
use aes_gcm::{
|
||||
aead::{Aead, AeadCore, KeyInit, OsRng},
|
||||
Aes256Gcm, Key, Nonce,
|
||||
};
|
||||
use axum::{Router, routing::get};
|
||||
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
|
||||
use sha2::{Digest, Sha256};
|
||||
use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
@@ -9,6 +16,26 @@ struct AppState {
|
||||
master_key: String,
|
||||
}
|
||||
|
||||
fn get_master_key(master_key: &str) -> Key<Aes256Gcm> {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(master_key.as_bytes());
|
||||
let result = hasher.finalize();
|
||||
*Key::<Aes256Gcm>::from_slice(&result)
|
||||
}
|
||||
|
||||
fn encrypt_secret(master_key: &str, plaintext: &str) -> String {
|
||||
let key = get_master_key(master_key);
|
||||
let cipher = Aes256Gcm::new(&key);
|
||||
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
|
||||
let ciphertext = cipher
|
||||
.encrypt(&nonce, plaintext.as_bytes())
|
||||
.expect("encryption failure");
|
||||
|
||||
let mut payload = nonce.to_vec();
|
||||
payload.extend_from_slice(&ciphertext);
|
||||
BASE64.encode(payload)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
tracing_subscriber::fmt()
|
||||
@@ -43,6 +70,28 @@ async fn main() {
|
||||
|
||||
tracing::info!("Migrations successful.");
|
||||
|
||||
if let Ok(file_content) = std::fs::read_to_string("secrets.json") {
|
||||
tracing::info!("Found secrets.json, provisioning");
|
||||
let secrets: HashMap<String, String> =
|
||||
serde_json::from_str(&file_content).expect("Invalid secrets.json format");
|
||||
|
||||
for (key, value) in secrets {
|
||||
let encrypted_val = encrypt_secret(&master_key, &value);
|
||||
sqlx::query(
|
||||
"INSERT INTO secrets (key_name, encrypted_value) VALUES (?, ?) ON CONFLICT(key_name) DO UPDATE SET encrypted_value = excluded.encrypted_value"
|
||||
)
|
||||
.bind(key)
|
||||
.bind(encrypted_val)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.expect("Failed to insert secret");
|
||||
}
|
||||
|
||||
std::fs::rename("secrets.json", "secrets.json.bak")
|
||||
.expect("Failed to rename secrets.json");
|
||||
tracing::info!("Provisioned secrets and renamed to secrets.json.bak");
|
||||
}
|
||||
|
||||
let state = AppState {
|
||||
pool,
|
||||
master_key,
|
||||
|
||||
Reference in New Issue
Block a user