diff --git a/README.md b/README.md index 08b573d..24e407a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,15 @@ ## Usage -You have two ways to set the four input values the tool needs. +In general this program can either output your ENV variables to use with `eval` or similar or it can run a program with populated environment. + +``` +# vault2env [secret path] [command] + + +# vault2env --export [secret path] +export ... +``` ### Using evironment variables ```bash diff --git a/main.go b/main.go index 234ed22..ae0896a 100644 --- a/main.go +++ b/main.go @@ -3,16 +3,21 @@ package main import ( "fmt" "log" + "os" + "os/exec" + "github.com/Luzifer/go_helpers/env" "github.com/Luzifer/rconfig" "github.com/hashicorp/vault/api" ) var ( cfg = struct { - VaultAddress string `flag:"vault-addr" env:"VAULT_ADDR" default:"https://127.0.0.1:8200" description:"Vault API address"` - VaultAppID string `flag:"vault-app-id" env:"VAULT_APP_ID" default:"" description:"The app-id to use for authentication"` - VaultUserID string `flag:"vault-user-id" env:"VAULT_USER_ID" default:"" description:"The user-id to use for authentication"` + VaultAddress string `flag:"vault-addr" env:"VAULT_ADDR" default:"https://127.0.0.1:8200" description:"Vault API address"` + VaultAppID string `flag:"vault-app-id" env:"VAULT_APP_ID" default:"" description:"The app-id to use for authentication"` + VaultUserID string `flag:"vault-user-id" env:"VAULT_USER_ID" default:"" description:"The user-id to use for authentication"` + Export bool `flag:"export,e" default:"false" description:"Show export statements instead of running the command specified"` + VersionAndExit bool `flag:"version" default:"false" description:"Print program version and exit"` }{} version = "dev" ) @@ -20,12 +25,23 @@ var ( func init() { rconfig.Parse(&cfg) + if cfg.VersionAndExit { + fmt.Printf("vault2env %s\n", version) + os.Exit(0) + } + if cfg.VaultAppID == "" || cfg.VaultUserID == "" { log.Fatalf("[ERR] You need to set vault-app-id and vault-user-id") } - if len(rconfig.Args()) != 2 { - log.Fatalf("[ERR] Exactly one argument is supported: The path of the key containing env variables") + if cfg.Export { + if len(rconfig.Args()) != 2 { + log.Fatalf("[ERR] Usage: vault2env --export [secret path]") + } + } else { + if len(rconfig.Args()) < 3 { + log.Fatalf("[ERR] Usage: vault2env [secret path] [command]") + } } } @@ -45,17 +61,31 @@ func main() { } client.SetToken(loginSecret.Auth.ClientToken) + defer client.Auth().Token().RevokeSelf(client.Token()) data, err := client.Logical().Read(rconfig.Args()[1]) if err != nil { log.Fatalf("Unable to fetch data: %s", err) } - for k, v := range data.Data { - fmt.Printf("export %s=\"%s\"\n", k, v) + if cfg.Export { + for k, v := range data.Data { + fmt.Printf("export %s=\"%s\"\n", k, v) + } + return } - if err := client.Auth().Token().RevokeSelf(client.Token()); err != nil { - log.Printf("Unable to clean up: %s", err) + emap := env.ListToMap(os.Environ()) + for k, v := range data.Data { + emap[k] = v.(string) + } + + cmd := exec.Command(rconfig.Args()[2], rconfig.Args()[2:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + cmd.Env = env.MapToList(emap) + if err := cmd.Run(); err != nil { + log.Fatal("Command exitted unclean (code != 0)") } }