mirror of
https://github.com/FliegendeWurst/KIT-ILIAS-downloader.git
synced 2024-08-28 04:04:18 +00:00
cli: Support for pass(1)
as credential storage
`pass(1)`[1] is a small CLI-based password manager. When passing `--pass-path edu/kit/uXXXX` to `KIT-ILIAS-Downloader`, it now attempts to retrieve the password from `pass(1)`. It is assumed that `pass(1)` is available in the `$PATH` of the process. If that's not the case, it errors out with an error like this: Error: credentials input failed Caused by: pass not found in $PATH! It's also taken care of the case where the value `--pass-path` is not present in the store, the error will look like this: Error: credentials input failed Caused by: `pass` failed with non-zero exit code 1: Error: edu/kit/uXXXX is not in the password store. Closes #32 [1] https://www.passwordstore.org/
This commit is contained in:
parent
f21c0249ed
commit
3a83840f15
35
src/cli.rs
35
src/cli.rs
@ -1,6 +1,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
@ -72,6 +74,10 @@ pub struct Opt {
|
|||||||
#[structopt(short = "P", long)]
|
#[structopt(short = "P", long)]
|
||||||
pub password: Option<String>,
|
pub password: Option<String>,
|
||||||
|
|
||||||
|
/// Path inside `pass(1)` to the password for shibboleth.
|
||||||
|
#[structopt(long)]
|
||||||
|
pub pass_path: Option<String>,
|
||||||
|
|
||||||
/// ILIAS page to download
|
/// ILIAS page to download
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub sync_url: Option<String>,
|
pub sync_url: Option<String>,
|
||||||
@ -170,6 +176,35 @@ pub fn ask_user_pass(opt: &Opt) -> Result<(String, String)> {
|
|||||||
should_store = true;
|
should_store = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some(pass_path) = &opt.pass_path {
|
||||||
|
let pw_out = Command::new("pass")
|
||||||
|
.arg("show")
|
||||||
|
.arg(pass_path)
|
||||||
|
.output()
|
||||||
|
.map_err(|x| {
|
||||||
|
if x.kind() == ErrorKind::NotFound {
|
||||||
|
Error::new(ErrorKind::NotFound, "pass not found in $PATH!")
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
if !pw_out.status.success() {
|
||||||
|
return Err(Error::new(
|
||||||
|
ErrorKind::Other,
|
||||||
|
format!(
|
||||||
|
"`pass` failed with non-zero exit code {}: {}",
|
||||||
|
pw_out.status.code()
|
||||||
|
.expect("Failed retrieving pass exit code!"),
|
||||||
|
String::from_utf8(pw_out.stderr)
|
||||||
|
.expect("Failed decoding stderr of pass!")
|
||||||
|
)
|
||||||
|
))?
|
||||||
|
} else {
|
||||||
|
pass = String::from_utf8(pw_out.stdout).map(|x| {
|
||||||
|
x.trim_end().to_string()
|
||||||
|
}).expect("utf-8 decode of `pass(1)`-output failed");
|
||||||
|
should_store = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pass = rpassword::prompt_password("Password: ").context("password prompt")?;
|
pass = rpassword::prompt_password("Password: ").context("password prompt")?;
|
||||||
should_store = true;
|
should_store = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user