-
Notifications
You must be signed in to change notification settings - Fork 3.5k
implement vault injection #9883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| use anyhow::Result; | ||
| use warp_cli::{vault::VaultCommand, GlobalOptions}; | ||
| use warp_vault::{ | ||
| config::{ProviderType, VaultConfig}, | ||
| inject_secrets, | ||
| provider::aws::AwsProvider, | ||
| }; | ||
| use warpui::AppContext; | ||
|
|
||
| pub fn run(_ctx: &mut AppContext, _global_options: GlobalOptions, command: VaultCommand) -> Result<()> { | ||
| match command { | ||
| VaultCommand::Inject(args) => { | ||
| let rt = tokio::runtime::Runtime::new()?; | ||
| rt.block_on(async { | ||
| let config = VaultConfig::load()?; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| let mappings = if let (Some(path), Some(env_var)) = (args.path, args.env_var) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| vec![warp_vault::config::SecretMapping { path, env_var }] | ||
| } else { | ||
| config.mappings() | ||
| }; | ||
|
|
||
| if mappings.is_empty() { | ||
| anyhow::bail!("vault: no mappings found — add entries to ~/.warp/vault.toml or pass a path and --as flag"); | ||
| } | ||
|
|
||
| let provider = match config.provider.provider_type { | ||
| ProviderType::Aws => AwsProvider::new(config.provider.region).await?, | ||
| }; | ||
|
|
||
| let secrets = inject_secrets(&provider, &mappings).await?; | ||
|
|
||
| for secret in &secrets { | ||
| println!("✓ {} injected as ${}", secret.env_var, secret.env_var); | ||
| } | ||
|
|
||
| Ok(()) | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| [package] | ||
| name = "warp_vault" | ||
| version = "0.1.0" | ||
| authors.workspace = true | ||
| publish.workspace = true | ||
| license.workspace = true | ||
| edition = "2024" | ||
|
|
||
| [dependencies] | ||
| anyhow.workspace = true | ||
| async-trait.workspace = true | ||
| log.workspace = true | ||
| serde.workspace = true | ||
| toml = "0.8" | ||
| zeroize = "1.8" | ||
| dirs = "5" | ||
| tokio = { version = "1", features = ["full"] } | ||
| aws-config = { version = "1", features = ["behavior-version-latest"] } | ||
| aws-sdk-secretsmanager = "1" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| #[cfg(test)] | ||
| #[path = "config_tests.rs"] | ||
| mod tests; | ||
|
|
||
| use std::{collections::HashMap, fs, path::PathBuf}; | ||
|
|
||
| use anyhow::{Context, Result}; | ||
| use serde::Deserialize; | ||
|
|
||
| #[derive(Debug, Deserialize)] | ||
| pub struct VaultConfig { | ||
| pub provider: ProviderConfig, | ||
| #[serde(default)] | ||
| pub mappings: HashMap<String, String>, | ||
| } | ||
|
|
||
| #[derive(Debug, Deserialize)] | ||
| pub struct ProviderConfig { | ||
| #[serde(rename = "type")] | ||
| pub provider_type: ProviderType, | ||
| pub region: Option<String>, | ||
| } | ||
|
|
||
| #[derive(Debug, Deserialize, PartialEq)] | ||
| #[serde(rename_all = "lowercase")] | ||
| pub enum ProviderType { | ||
| Aws, | ||
| } | ||
|
|
||
| pub struct SecretMapping { | ||
| pub path: String, | ||
| pub env_var: String, | ||
| } | ||
|
|
||
| impl VaultConfig { | ||
| pub fn load() -> Result<Self> { | ||
| let path = config_path(); | ||
| let contents = fs::read_to_string(&path).with_context(|| { | ||
| format!( | ||
| "no config found at {} — run 'oz vault init' to get started", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| path.display() | ||
| ) | ||
| })?; | ||
| toml::from_str(&contents).context("failed to parse vault config") | ||
| } | ||
|
|
||
| pub fn mappings(&self) -> Vec<SecretMapping> { | ||
| self.mappings | ||
| .iter() | ||
| .map(|(path, env_var)| SecretMapping { | ||
| path: path.clone(), | ||
| env_var: env_var.clone(), | ||
| }) | ||
| .collect() | ||
| } | ||
| } | ||
|
|
||
| fn config_path() -> PathBuf { | ||
| dirs::home_dir() | ||
| .unwrap_or_default() | ||
| .join(".warp") | ||
| .join("vault.toml") | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oz vault inject <path> --as <env>fail when~/.warp/vault.tomlis absent, despite the CLI advertising that path/--ascan be used instead. Defer config loading until config-backed mappings are needed or allow AWS defaults for one-off injections.