use std::path::{Path, PathBuf};
use crate::error::Error;
use crate::policy::Policy;
use crate::secret_health;
use crate::vault::Vault;
#[derive(Debug, Clone)]
pub struct PolicyRuleView {
pub binary: String,
pub secret: String,
pub scope: String,
}
pub fn policy_show() -> Result<Vec<PolicyRuleView>, Error> {
let vault = Vault::open_default()?;
policy_show_in(&vault)
}
pub fn policy_show_in(vault: &Vault) -> Result<Vec<PolicyRuleView>, Error> {
let policy_path = vault.policy_path();
let policy = Policy::load_sealed(&policy_path, vault.master_key_bytes())?;
Ok(policy
.rules
.iter()
.map(|r| PolicyRuleView {
binary: r.binary.clone(),
secret: r.secret.clone(),
scope: format!("{:?}", r.scope).to_lowercase(),
})
.collect())
}
pub fn policy_revoke_binary(binary: &str) -> Result<(), Error> {
let vault = Vault::open_default()?;
policy_revoke_binary_in(&vault, binary)
}
pub fn policy_revoke_binary_in(vault: &Vault, binary: &str) -> Result<(), Error> {
let canonical = std::path::Path::new(binary).canonicalize().map_err(|e| {
Error::BinaryResolution(format!(
"cannot canonicalize '{binary}' for policy revoke: {e}. \
Fix: provide the absolute path to the binary as stored in 'envseal policy show'."
))
})?;
let canonical_str = canonical.to_string_lossy().into_owned();
let policy_path = vault.policy_path();
let mut policy = Policy::load_sealed(&policy_path, vault.master_key_bytes())?;
policy.revoke_binary(&canonical_str);
policy.save_sealed(&policy_path, vault.master_key_bytes())?;
Ok(())
}
pub fn git_hook_install() -> Result<PathBuf, Error> {
let hook_dir = Path::new(".git/hooks");
if !hook_dir.exists() {
return Err(Error::StorageIo(std::io::Error::new(
std::io::ErrorKind::NotFound,
"not in a git repository (no .git/hooks directory)",
)));
}
let hook_path = hook_dir.join("pre-commit");
if hook_path.exists() {
return Err(Error::SecretAlreadyExists(format!(
"pre-commit hook already exists at {}",
hook_path.display()
)));
}
std::fs::write(&hook_path, secret_health::pre_commit_hook())?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&hook_path, std::fs::Permissions::from_mode(0o755))?;
}
Ok(hook_path)
}
#[must_use]
pub fn git_hook_script() -> &'static str {
secret_health::pre_commit_hook()
}
#[must_use]
pub fn gitignore_snippet() -> &'static str {
secret_health::gitignore_snippet()
}