Öffentliche Dateiansicht: Raw-Dateien, Tree, Releases und Issues sind ohne Login verfügbar.
cmd/load.go Raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
package cmd

import (
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/spf13/cobra"
	"golang.org/x/term"
)

func init() {
	rootCmd.AddCommand(newLoadCmd())
}

func newLoadCmd() *cobra.Command {
	var shell string
	var reveal bool

	cmd := &cobra.Command{
		Use:   "load",
		Short: "Output export statements for eval in the current shell",
		Long: `Outputs shell export statements so secrets are available in the current session.

  eval "$(envault load)"              # bash / zsh — values never printed on screen
  envault load --shell fish | source  # fish

Uses an active session (envault open) if available — no password prompt needed.
When run directly in a terminal, values are masked for safety.
Use --reveal to print actual values to the terminal.`,
		Args: cobra.NoArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			project := resolveProject()
			var vars map[string]string

			// Priority 1: active session
			if sv := trySession(); sv != nil {
				vars = sv
			} else {
				// Priority 2: full vault (prompts for password)
				v, _, _, err := openVault()
				if err != nil {
					return err
				}
				vars = v.GetAll(project)
			}

			if len(vars) == 0 {
				fmt.Fprintf(os.Stderr, "No secrets in project %q\n", project)
				return nil
			}

			keys := make([]string, 0, len(vars))
			for k := range vars {
				keys = append(keys, k)
			}
			sort.Strings(keys)

			// When stdout is a terminal the user ran "envault load" directly.
			// Show a masked preview so values don't appear on screen.
			// When stdout is a pipe (eval "$(envault load)") output real values.
			isTTY := term.IsTerminal(int(os.Stdout.Fd()))

			if isTTY && !reveal {
				shellName := strings.ToLower(shell)
				fmt.Fprintf(os.Stderr, "Project: %s  (%d secret(s))\n\n", project, len(keys))
				for _, k := range keys {
					switch shellName {
					case "fish":
						fmt.Printf("set -x %s ••••••••\n", k)
					default:
						fmt.Printf("export %s=••••••••\n", k)
					}
				}
				fmt.Fprintf(os.Stderr, "\nRun:  eval \"$(envault load)\"  to load into your shell.\n")
				return nil
			}

			// Real output — for eval or --reveal
			switch strings.ToLower(shell) {
			case "fish":
				for _, k := range keys {
					fmt.Printf("set -x %s %s;\n", k, fishQuote(vars[k]))
				}
			default:
				for _, k := range keys {
					fmt.Printf("export %s=%s\n", k, shQuote(vars[k]))
				}
			}
			return nil
		},
	}

	cmd.Flags().StringVar(&shell, "shell", "sh", "shell format: sh, bash, zsh, fish")
	cmd.Flags().BoolVar(&reveal, "reveal", false, "print actual values to the terminal (use with care)")
	return cmd
}

func shQuote(s string) string {
	return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
}

func fishQuote(s string) string {
	return "'" + strings.ReplaceAll(s, "'", `\'`) + "'"
}