Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ services:
- .:/app
- cargo-registry:/usr/local/cargo/registry
- cargo-git:/usr/local/cargo/git
- ./databases.json:/config/config.json
- /Users/charlesgauthereau/Desktop/test-portabase/databases.json:/config/config.json
# - ./databases.json:/config/config.json
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
#- ./databases.toml:/config/config.toml
#- /var/run/docker.sock:/var/run/docker.sock
#- cargo-target:/app/target
Expand All @@ -19,7 +20,7 @@ services:
APP_ENV: development
LOG: debug
TZ: "Europe/Paris"
EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNzM0NjU3Y2YtMGQzYy00Y2UwLTkyODQtZDJmOGYyMjI2MzgzIiwibWFzdGVyS2V5QjY0IjoiMUh0djdtWCtYVkJxL0IzUEV2WDlZZjlQeUdVZW5oRHlXemo5THRqNW90WT0ifQ=="
EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNjIyNWFlMzMtODQwMy00NmE3LWEyNDEtMjU4MTI2MjVlYTA4IiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ=="

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Likely credential leak — rotate immediately.

The new EDGE_KEY base64-decodes to a JSON payload containing serverUrl, agentId, and masterKeyB64. Committing this value into a tracked file in a shared repo is equivalent to publishing the master key. Two actions are required:

  1. Rotate the master key on the server side and reissue a fresh EDGE_KEY for this agent — assume the current value is compromised the moment this PR is pushed.
  2. Move the value out of docker-compose.yml. Use a non-tracked .env (gitignored) or a developer-local override file (docker-compose.override.yml) and reference it via ${EDGE_KEY}.
🔒 Proposed fix
-      EDGE_KEY: "eyJzZXJ2ZXJVcmwi...=="
+      EDGE_KEY: ${EDGE_KEY:?EDGE_KEY must be provided via .env}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNjIyNWFlMzMtODQwMy00NmE3LWEyNDEtMjU4MTI2MjVlYTA4IiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ=="
EDGE_KEY: ${EDGE_KEY:?EDGE_KEY must be provided via .env}
🧰 Tools
🪛 Betterleaks (1.1.2)

[high] 23-23: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 23-23: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose.yml` at line 23, The commit leaks a sensitive EDGE_KEY value
in docker-compose.yml (the EDGE_KEY environment variable); rotate the exposed
master key on the server immediately and remove the hard-coded value from
docker-compose.yml, then reference a runtime variable (e.g., ${EDGE_KEY})
instead and load it from a gitignored .env or docker-compose.override.yml kept
out of source control; update any deployment docs or dev README to show how to
provision EDGE_KEY locally and ensure docker-compose.yml no longer contains the
literal key.

#CHUNK_SIZE_MB: "1"
#POOLING: 1
#DATABASES_CONFIG_FILE: "config.toml"
Expand Down
7 changes: 4 additions & 3 deletions src/domain/mariadb/backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub async fn run(
let mariadb_dump = select_mariadb_path(&version).join("mariadb-dump");
info!("Mariadb dump found: {}", mariadb_dump.display());


let output = Command::new("mariadb-dump")
Comment on lines 33 to 37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

mariadb_dump is resolved by version but never used — falls back to $PATH.

Lines 33–34 compute and log a version-specific path, then line 37 spawns the bare string "mariadb-dump", which makes select_mariadb_path effectively dead code and breaks the per-version targeting. If the host has multiple mariadb-dump binaries (or none on $PATH), behavior diverges from what the log line claims.

🔧 Proposed fix
-        let output = Command::new("mariadb-dump")
+        let output = Command::new(&mariadb_dump)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let mariadb_dump = select_mariadb_path(&version).join("mariadb-dump");
info!("Mariadb dump found: {}", mariadb_dump.display());
let output = Command::new("mariadb-dump")
let mariadb_dump = select_mariadb_path(&version).join("mariadb-dump");
info!("Mariadb dump found: {}", mariadb_dump.display());
let output = Command::new(&mariadb_dump)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/domain/mariadb/backup.rs` around lines 33 - 37, The code computes a
version-specific path into the mariadb_dump variable via
select_mariadb_path(&version) but then calls Command::new("mariadb-dump"),
ignoring that path; replace the hardcoded Command::new("mariadb-dump") with a
call that uses the computed mariadb_dump (e.g., pass mariadb_dump or
mariadb_dump.as_os_str() / mariadb_dump.as_path() to Command::new) so the
spawned process uses the version-specific binary selected by select_mariadb_path
and matches the logged path.

.arg("--host").arg(&cfg.host)
.arg("--port").arg(cfg.port.to_string())
Expand All @@ -43,18 +44,18 @@ pub async fn run(
.arg("--single-transaction")
.arg("--quick")
.arg("--skip-lock-tables")
.arg("--add-drop-database")
.arg("--databases").arg(&cfg.database)
.arg("--no-create-db")
.arg("--skip-add-drop-table")
.arg("--compress")
.arg("--max-allowed-packet=512M")
.arg("--net-buffer-length=16K")
.arg("--default-character-set=utf8mb4")
.arg(&cfg.database)
.arg("-r").arg(&file_path)
.envs(env)
.output()
.with_context(|| format!("Failed to run mariadb-dump for {}", cfg.name))?;


if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("Mariadb backup failed for {}: {}", cfg.name, stderr);
Expand Down
3 changes: 2 additions & 1 deletion src/domain/mariadb/restore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> {
.arg(cfg.port.to_string())
.arg("--user")
.arg(&cfg.username)
.arg("--database")
.arg(&cfg.database)
.env("MYSQL_PWD", &cfg.password)
.stdin(std::process::Stdio::piped())
Expand Down Expand Up @@ -77,4 +78,4 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> {
handle.await??;

Ok(())
}
}
16 changes: 7 additions & 9 deletions src/domain/mysql/backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,23 @@ pub async fn run(

let file_path = backup_dir.join(format!("{}{}", cfg.generated_id, file_extension));

// let mysql_dump = select_mysql_path(&version).join("mysqldump");
// info!("MySQL dump found: {}", mysql_dump.display());

let output = Command::new("mysqldump")
.arg("--host")
.arg(cfg.host)
.arg(&cfg.host)
.arg("--port")
.arg(cfg.port.to_string())
.arg("--user")
.arg(cfg.username)
.arg(&cfg.username)
.arg("--routines")
.arg("--events")
.arg("--triggers")
.arg("--verbose")
.arg("--single-transaction")
.arg("--quick")
.arg("--add-drop-database")
.arg("--databases")
.arg(cfg.database)
.arg("--skip-lock-tables")
.arg("--skip-add-drop-table")
.arg("--no-create-db") // IMPORTANT
.arg("--default-character-set=utf8mb4")
.arg(&cfg.database) // IMPORTANT: NOT --databases
.arg("-r")
.arg(&file_path)
.envs(env)
Expand Down
1 change: 1 addition & 0 deletions src/domain/mysql/restore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> {
.arg(cfg.port.to_string())
.arg("--user")
.arg(&cfg.username)
.arg("--database")
.arg(&cfg.database)
.env("MYSQL_PWD", &cfg.password)
.stdin(std::process::Stdio::piped())
Expand Down
10 changes: 5 additions & 5 deletions src/domain/postgres/restore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ pub async fn run(
info!("Connections terminated for database {}", cfg.name);

let url = format!(
"postgresql://{}:{}@{}:{}/postgres",
cfg.username, cfg.password, cfg.host, cfg.port
"postgresql://{}:{}@{}:{}/{}",
cfg.username, cfg.password, cfg.host, cfg.port, cfg.database
);

debug!("Restore URL: {}", url);
Expand All @@ -51,7 +51,7 @@ pub async fn run(
.arg("--no-privileges")
.arg("--clean")
.arg("--if-exists")
.arg("--create")
// .arg("--create")
.arg("--dbname")
.arg(&url)
.arg("-v")
Expand Down Expand Up @@ -139,8 +139,8 @@ pub async fn run(
.arg("--no-privileges")
.arg("--clean")
.arg("--if-exists")
.arg("--create")
.arg("--dbname")
// .arg("--create")
.arg("--dbname={}")
.arg(&url)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
.arg("-v")
.arg("-j")
Expand Down
Loading