macOS: API-Key nicht mehr ueber die Kommandozeile an security
add-generic-password bekam den Key als -w-Argument; damit stand er fuer die Dauer des Aufrufs in der Prozessliste und war per ps fuer jeden Nutzer des Rechners lesbar. Jetzt kommt -w ohne Wert, security liest das Secret ueber stdin (zweimal, Eingabe und Bestaetigung). Die Eingabeaufforderungen landen auf stderr und werden aus der Fehlermeldung geschnitten.
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
//! macOS: Aktivierung/Fokus über AppKit (objc2), Dock-Icons pro
|
||||
//! Terminal-Prozess, Keychain über das security-CLI, nativer Tray.
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use crate::domain::credentials::{ApikeyStore, APIKEY_SERVICE};
|
||||
use crate::domain::paths::Paths;
|
||||
@@ -98,14 +99,32 @@ pub(crate) struct KeychainStore;
|
||||
|
||||
impl ApikeyStore for KeychainStore {
|
||||
fn set(&self, pool: &str, key: &str) -> Result<(), String> {
|
||||
let out = Command::new("security")
|
||||
.args(["add-generic-password", "-U", "-s", APIKEY_SERVICE, "-a", pool, "-w", key])
|
||||
.output()
|
||||
// -w ohne Wert: security liest das Secret über stdin, zweimal (Eingabe und
|
||||
// Bestätigung). Als Argument übergeben stünde der Key für die Dauer des
|
||||
// Aufrufs in der Prozessliste und wäre für jeden `ps` lesbar.
|
||||
let mut child = Command::new("security")
|
||||
.args(["add-generic-password", "-U", "-s", APIKEY_SERVICE, "-a", pool, "-w"])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| e.to_string())?;
|
||||
child
|
||||
.stdin
|
||||
.take()
|
||||
.ok_or("security: kein stdin")?
|
||||
.write_all(format!("{key}\n{key}\n").as_bytes())
|
||||
.map_err(|e| e.to_string())?;
|
||||
let out = child.wait_with_output().map_err(|e| e.to_string())?;
|
||||
if out.status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(String::from_utf8_lossy(&out.stderr).into_owned())
|
||||
// Die Eingabeaufforderungen landen auf stderr und stehen sonst vor der
|
||||
// eigentlichen Fehlermeldung.
|
||||
let err = String::from_utf8_lossy(&out.stderr)
|
||||
.replace("password data for new item: ", "")
|
||||
.replace("retype password for new item: ", "");
|
||||
Err(err.trim().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user