mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat(cli): add an option to specify the encrypt password in a file
This commit is contained in:
Generated
+1
-1
@@ -424,7 +424,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bichon"
|
name = "bichon"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"async-imap",
|
"async-imap",
|
||||||
|
|||||||
@@ -449,9 +449,12 @@ cargo build
|
|||||||
Or run directly:
|
Or run directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
export BICHON_ENCRYPT_PASSWORD=dummy-password-for-testing
|
||||||
cargo run -- --bichon-root-dir e:\bichon-data
|
cargo run -- --bichon-root-dir e:\bichon-data
|
||||||
```
|
```
|
||||||
|
|
||||||
`--bichon-root-dir` specifies the directory where **all Bichon data** will be stored.
|
`--bichon-root-dir` specifies the directory where **all Bichon data** will be stored.
|
||||||
|
`BICHON_ENCRYPT_PASSWORD` is the password used to encrypt the sensitive data (see `cargo run -- --help` for alternative ways to specify this).
|
||||||
|
|
||||||
### WebUI Access
|
### WebUI Access
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
use clap::{builder::ValueParser, Parser, ValueEnum};
|
use clap::{builder::ValueParser, Parser, ValueEnum};
|
||||||
use std::{collections::HashSet, env, fmt, path::PathBuf, sync::LazyLock};
|
use std::{collections::HashSet, env, fmt, path::PathBuf, sync::LazyLock};
|
||||||
|
|
||||||
pub static SETTINGS: LazyLock<Settings> = LazyLock::new(Settings::parse);
|
pub static SETTINGS: LazyLock<Settings> = LazyLock::new(Settings::init);
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[clap(
|
||||||
@@ -132,11 +132,17 @@ pub struct Settings {
|
|||||||
/// bichon encryption password
|
/// bichon encryption password
|
||||||
#[clap(
|
#[clap(
|
||||||
long,
|
long,
|
||||||
default_value = "change-this-default-password-now",
|
|
||||||
env,
|
env,
|
||||||
help = "Set the encryption password for bichon. ⚠️ Change this default in production!"
|
help = "Set the encryption password for bichon. Alternatively, you can use --bichon-encrypt-password-file. If both are set, this parameter takes precedence over the file."
|
||||||
)]
|
)]
|
||||||
pub bichon_encrypt_password: String,
|
pub bichon_encrypt_password: Option<String>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
env,
|
||||||
|
help = "The file containing the encryption password. An alternative to --bichon-encrypt-password."
|
||||||
|
)]
|
||||||
|
pub bichon_encrypt_password_file: Option<String>,
|
||||||
|
|
||||||
#[clap(
|
#[clap(
|
||||||
long,
|
long,
|
||||||
@@ -217,6 +223,18 @@ pub struct Settings {
|
|||||||
pub bichon_sync_concurrency: Option<u16>,
|
pub bichon_sync_concurrency: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
pub fn init() -> Self {
|
||||||
|
let s = Self::parse();
|
||||||
|
if s.bichon_encrypt_password.is_none() && s.bichon_encrypt_password_file.is_none() {
|
||||||
|
panic!(
|
||||||
|
"One of --bichon_encrypt_password or --bichon_encrypt_password_file has to be set"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, ValueEnum)]
|
#[derive(Clone, Copy, Debug, PartialEq, ValueEnum)]
|
||||||
pub enum CompressionAlgorithm {
|
pub enum CompressionAlgorithm {
|
||||||
#[clap(name = "none")]
|
#[clap(name = "none")]
|
||||||
|
|||||||
@@ -16,18 +16,30 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use ring::aead::{Aad, BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey, AES_256_GCM};
|
use ring::aead::{Aad, BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey, AES_256_GCM};
|
||||||
use ring::pbkdf2::{self, derive};
|
use ring::pbkdf2::{self, derive};
|
||||||
use ring::rand::{SecureRandom, SystemRandom};
|
use ring::rand::{SecureRandom, SystemRandom};
|
||||||
|
use std::fs;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use crate::modules::error::code::ErrorCode;
|
use crate::modules::error::code::ErrorCode;
|
||||||
use crate::modules::error::BichonResult;
|
use crate::modules::error::BichonResult;
|
||||||
use crate::modules::settings::cli::SETTINGS;
|
use crate::modules::settings::cli::SETTINGS;
|
||||||
use crate::raise_error;
|
use crate::raise_error;
|
||||||
|
|
||||||
|
static ENCRYPT_PASSWORD: LazyLock<String> =
|
||||||
|
LazyLock::new(|| match &SETTINGS.bichon_encrypt_password {
|
||||||
|
Some(p) => p.clone(),
|
||||||
|
None => {
|
||||||
|
// unwrap() is safe here, because SETTINGS validates that at least one of the encrypt_password
|
||||||
|
// fields is set.
|
||||||
|
fs::read_to_string(SETTINGS.bichon_encrypt_password_file.as_ref().unwrap())
|
||||||
|
.expect("failed to read the file with the encrypt password")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
struct SingleNonceSequence([u8; 12]);
|
struct SingleNonceSequence([u8; 12]);
|
||||||
|
|
||||||
impl SingleNonceSequence {
|
impl SingleNonceSequence {
|
||||||
@@ -43,12 +55,12 @@ impl NonceSequence for SingleNonceSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt_string(plaintext: &str) -> BichonResult<String> {
|
pub fn encrypt_string(plaintext: &str) -> BichonResult<String> {
|
||||||
internal_encrypt_string(&SETTINGS.bichon_encrypt_password, plaintext)
|
internal_encrypt_string(&ENCRYPT_PASSWORD, plaintext)
|
||||||
.map_err(|_| raise_error!("Failed to encrypt string.".into(), ErrorCode::InternalError))
|
.map_err(|_| raise_error!("Failed to encrypt string.".into(), ErrorCode::InternalError))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt_string(data: &str) -> BichonResult<String> {
|
pub fn decrypt_string(data: &str) -> BichonResult<String> {
|
||||||
internal_decrypt_string(&SETTINGS.bichon_encrypt_password, data).map_err(|_| {
|
internal_decrypt_string(&ENCRYPT_PASSWORD, data).map_err(|_| {
|
||||||
raise_error!(
|
raise_error!(
|
||||||
"Decryption failed, likely due to incorrect encryption key or corrupted data".into(),
|
"Decryption failed, likely due to incorrect encryption key or corrupted data".into(),
|
||||||
ErrorCode::InternalError
|
ErrorCode::InternalError
|
||||||
|
|||||||
Reference in New Issue
Block a user