Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var Decrypt = &cobra.Command{ Use: "decrypt", Short: "Decrypt key(s) and print to stdout", RunE: func(cmd *cobra.Command, args []string) error { config, err := config.GetConfig() if err != nil { return err } keeper, err := crypt.NewKeeper(config.Encryption.Type, config.Encryption.KeyPath) if err != nil { return err } var envKeys []string switch allKeys { case true: envKeys = config.Env.Keys() default: err = validateEnv(config.Env, args) if err != nil { return err } envKeys = args } for _, key := range envKeys { value, err := keeper.Decrypt(key, config.Env[key]) if err != nil { log. WithField("err", err.Error()). Warn("failed to decrypt value") } if withKey { fmt.Printf("%s=%s\n", key, value) } else { fmt.Printf("%s\n", value) } } return nil }, }
View Source
var Direnv = &cobra.Command{ Use: "direnv", Short: "Integrate with direnv", Args: cobra.ExactArgs(1), ValidArgs: []string{"bash", "zsh", "fish"}, RunE: func(cmd *cobra.Command, args []string) error { cfg, err := config.GetConfig() if err != nil { return err } sh := shell.Detect(args[0]) envrcPath := direnv.EnvrcPath() var integrate bool switch { case yesPrompt: if len(envrcPath) > 0 { integrate = true } else { logrus.Println("No .envrc file detected. Skipping direnv integration.") } case len(envrcPath) > 0: output := promptUserf(".envrc file detected at %s. Would you like to integrate with direnv? [Y/n]: ", envrcPath) if output == "y" || output == "yes" { integrate = true } } if integrate { if !direnv.IsInstalled() { fmt.Println(`"direnv" is not installed. Install "direnv" and try again`) os.Exit(1) } exists, err := fileutils.TextExistsInFile(envrcPath, fmt.Sprintf(`eval "$(cryptkeeper export %s)"`, sh.Shell())) if err != nil || !exists { fmt.Printf("Add the following to your .envrc file:\n\n%s\n\n", direnv.EvalStatement(sh.Shell())) } _ = direnv.Reload() cfg.Mode = config.DirenvMode } else { return nil } err = config.Write(cfg) if err != nil { return fmt.Errorf("error writing config: %w", err) } return nil }, }
View Source
var Env = &cobra.Command{ Use: "env", Short: "Export or unset decrypted environment variables", Hidden: true, Args: cobra.ExactArgs(1), ValidArgs: []string{"bash", "zsh", "fish"}, Run: func(cmd *cobra.Command, args []string) { sh := shell.Detect(args[0]) cfg, err := config.GetConfig() if err != nil { pathErr := new(*os.PathError) if (errors.Is(err, fileutils.ErrFileNotFound) || errors.As(err, pathErr)) && envVarExists(config.CKWatchEnvKey) && envVarExists(config.CKRevertEnvKey) { fmt.Print(unloadDiff(config.CKRevertEnvKey, sh)) } return } if watchPath, ok := os.LookupEnv(config.CKWatchEnvKey); ok && watchPath != cfg.Path { diffString := unloadDiff(config.CKRevertEnvKey, sh) log.WithFields(log.Fields{ "watch_path": watchPath, "config_path": cfg.Path, "diff": diffString, }).Debug("reverting env") fmt.Print(diffString) } if cfg.Mode == config.DirenvMode { fmt.Print(sh.Unset(config.CKRevertEnvKey) + sh.Unset(config.CKLastEnvKey)) return } keeper, err := crypt.NewKeeper(cfg.Encryption.Type, cfg.Encryption.KeyPath) if err != nil { return } cwd, err := os.Getwd() if err != nil { return } exportEnv, err := fileutils.IsChildDirOrSame(cwd, filepath.Dir(cfg.Path)) if err != nil { return } if !exportEnv { fmt.Print(unloadDiff(config.CKRevertEnvKey, sh)) return } lastEnv, err := envdiff.FetchLastEnv(config.CKLastEnvKey, keeper) if err != nil { log.WithError(err).Debug("failed to fetch last env") return } revertEnv, err := envdiff.FetchRevert(config.CKRevertEnvKey) if err != nil { log.WithError(err).Debug("failed to fetch revert enkv") return } currentEnv := cfg.Env err = currentEnv.Decrypt(keeper) if err != nil { log.WithError(err).Debug("failed to decrypt env") return } var firstLoad bool if loading() { log.Info("cryptkeeper: loading") firstLoad = true } log.WithFields(log.Fields{ "CURRENT_ENV": currentEnv, "LAST_ENV": lastEnv, "REVERT_ENV": revertEnv, }).Debug("envs") if sameEnv(lastEnv, currentEnv) && len(revertEnv) == len(lastEnv) { log.Debug("cryptkeeper: no changes") if firstLoad { diffString := exportAllEnvs(cfg.Path, currentEnv, revertEnv, sh, keeper) log.WithField("diff", diffString).Debug("exporting") fmt.Print(diffString) } return } if out := diffStatus(envdiff.BuildEnvDiff(lastEnv, currentEnv)); out != "" { log.Infof("cryptkeeper: export %s", out) } newLast := lastEnv.Copy() for k, v := range currentEnv { if !utils.In(k, revertEnv) && !utils.In(k, lastEnv) { val, ok := os.LookupEnv(k) if ok { revertEnv[k] = utils.ToPtr(val) } else { revertEnv[k] = nil } } newLast[k] = v } for k := range lastEnv { if !utils.In(k, currentEnv) { delete(newLast, k) } } newRevertEnv := lo.MapValues(revertEnv, func(value *string, _ string) string { if value == nil { return "" } return *value }) log.WithField("env", newRevertEnv).Debug("new revert env") diffString := envdiff.BuildEnvDiff(newRevertEnv, newLast).ToShell(sh) for k := range newRevertEnv { if !utils.In(k, newLast) { delete(revertEnv, k) } } diffString += exportAllEnvs(cfg.Path, currentEnv, revertEnv, sh, keeper) log.Debugf("env diff %s", diffString) fmt.Print(diffString) }, }
View Source
var Export = &cobra.Command{ Use: "export", Short: "Export decrypted environment variables", Hidden: true, Args: cobra.ExactArgs(1), ValidArgs: []string{"bash", "zsh", "fish"}, Run: func(cmd *cobra.Command, args []string) { cfg, err := config.GetConfig() if err != nil { return } target := args[0] sh := shell.Detect(target) if target == "fish" { sh = shell.Bash } keeper, err := crypt.NewKeeper(cfg.Encryption.Type, cfg.Encryption.KeyPath) if err != nil { return } exported := "" for key, cipher := range cfg.Env { decryptedValue, err := keeper.Decrypt(key, cipher) if err != nil { log. WithField("err", err.Error()). Warn("failed to decrypt value") } exported += sh.Export(key, decryptedValue) } exported += sh.Export(config.CKWatchEnvKey, cfg.Path) if _, ok := os.LookupEnv(config.CKWatchEnvKey); !ok { log.Info("cryptkeeper: loading") } fmt.Print(exported) }, }
View Source
var Hook = &cobra.Command{ Use: "hook", Short: "Prints the shell hook to stdout", Hidden: true, Args: cobra.ExactArgs(1), ValidArgs: []string{"bash", "zsh", "fish"}, RunE: func(cmd *cobra.Command, args []string) error { selfPath, err := os.Executable() if err != nil { return err } selfPath = strings.Replace(selfPath, "\\", "/", -1) ctx := hookContext{ SelfPath: selfPath, } sh := shell.Detect(args[0]) hookTemplate, err := template.New("hook").Parse(sh.Hook()) if err != nil { return err } err = hookTemplate.Execute(os.Stdout, ctx) if err != nil { return err } return nil }, }
View Source
var Init = &cobra.Command{ Use: "init", Short: "Initialize cryptkeeper", Args: cobra.ExactArgs(1), ValidArgs: []string{"bash", "zsh", "fish"}, RunE: func(cmd *cobra.Command, args []string) error { keyPath = fileutils.Clean(keyPath) configPath := fileutils.Clean(config.FileName()) if fileutils.FileExists(keyPath) { return fmt.Errorf("key file already exists at %s", keyPath) } if fileutils.FileExists(configPath) { return fmt.Errorf("config file already exists at %s", fileutils.Clean(config.FileName())) } var encType crypt.EncryptionType var err error switch strings.ToLower(encryption) { case "aes", "aes256", "aes-256": encType = crypt.AES256 case "rsa", "rsa2048", "rsa-2048": encType = crypt.RSA2048 case "ecc", "ecc256", "ecc-256": encType = crypt.ECC256 case "serpent", "serpent256", "serpent-256": encType = crypt.Serpent256 default: return crypt.ErrUnknownEncryptionType } err = crypt.GenerateKeys(encType, keyPath) if err != nil { return err } cfg := &config.Config{ Encryption: config.Encryption{ KeyPath: keyPath, Type: encType, }, Env: make(config.Env), Path: configPath, } envrcPath := direnv.EnvrcPath() sh := shell.Detect(args[0]) var integrate bool switch { case standalone: fmt.Println("Running in standalone mode. Skipping direnv integration.") default: integrate = true } if integrate { if !direnv.IsInstalled() { fmt.Println("direnv is not installed. Please install direnv before adding secrets.") } exists, err := fileutils.TextExistsInFile(envrcPath, fmt.Sprintf(`eval "$(cryptkeeper export %s)"`, sh.Shell())) if err != nil || !exists { fmt.Printf("Add this to your .envrc file:\n\n%s\n\n", direnv.EvalStatement(sh.Shell())) } cfg.Mode = config.DirenvMode } else { rcPath, err := fileutils.FindPathTo(sh.RCFile()) var exists bool if len(rcPath) > 0 { exists, err = fileutils.TextExistsInFile(rcPath, fmt.Sprintf(`eval "$(cryptkeeper hook %s)"`, sh.Shell())) } if err != nil || !exists { fmt.Printf("Add this to your %s file:\n\neval \"$(cryptkeeper hook %s)\"\n\n", sh.RCFile(), sh.Shell()) } cfg.Mode = config.StandaloneMode } err = config.Init(cfg) if err != nil { return fmt.Errorf("error writing config: %w", err) } fmt.Printf("Initialized config in %s and key in %s\n", fileutils.Clean(config.FileName()), keyPath) return nil }, }
View Source
var Remove = &cobra.Command{ Use: "remove", Short: "Remove one or more key-value pairs from the config", RunE: func(cmd *cobra.Command, args []string) error { cfg, err := config.GetConfig() if err != nil { return err } envKeys := args if allKeys { envKeys = cfg.Env.Keys() } for _, key := range envKeys { delete(cfg.Env, key) } if cfg.Encryption.Type == crypt.ECC256 { keeper, err := crypt.NewKeeper(cfg.Encryption.Type, cfg.Encryption.KeyPath) if err != nil { logrus. WithError(err). Debug("failed to remove encryption keys") } if keeper != nil { for _, envKey := range envKeys { err = keeper.RemoveKey(envKey) if err != nil { logrus. WithError(err). Debugf("failed to remove encryption key for %s", envKey) } } } } err = config.Write(cfg) if err != nil { return err } if cfg.IsDirenvIntegrated() { return direnv.ReloadEnv() } return nil }, }
View Source
var Set = &cobra.Command{ Use: "set", Aliases: []string{"add"}, Short: "Set a new key-value pair", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { key, value := args[0], "" cfg, err := config.GetConfig() if err != nil { return errors.New("failed to get config") } switch { case useClipboard: value, err = clipboard.ReadAll() if err != nil { logrus. WithError(err). Warn("failed to get value from clipboard") } case isInputPiped(): reader := bufio.NewReader(os.Stdin) value, err = reader.ReadString('\n') if err != nil { logrus. WithError(err). Warn("failed to get piped in value") } } if value == "" { fmt.Print("Enter value (it won't be displayed):\n") byteValue, err := term.ReadPassword(int(os.Stdin.Fd())) if err != nil { return fmt.Errorf("error reading value: %w", err) } value = string(byteValue) } value = strings.TrimSuffix(value, "\n") keeper, err := crypt.NewKeeper(cfg.Encryption.Type, cfg.Encryption.KeyPath) if err != nil { return err } encryptedValue, err := keeper.Encrypt(key, value) if err != nil { return fmt.Errorf("failed to encrypt value: %w", err) } if cfg.Env == nil { cfg.Env = make(map[string]string) } cfg.Env[key] = encryptedValue err = config.Write(cfg) if err != nil { return errors.New("failed to write config") } if cfg.IsDirenvIntegrated() { return direnv.ReloadEnv() } return nil }, }
View Source
var Verify = &cobra.Command{ Use: "verify", Aliases: []string{"check"}, Short: "Verifies the encrypted value of a specified secret key", Long: "Verifies if the provided value matches the encrypted value of a specified secret key, without revealing the actual secret. Useful for confirming the integrity or correctness of a stored secret.", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { envKey, expectedValue := args[0], "" cfg, err := config.GetConfig() if err != nil { return errors.New("failed to get config") } cipher, ok := cfg.Env[envKey] if !ok { return fmt.Errorf("secret %s does not exist", envKey) } switch { case useClipboard: expectedValue, err = clipboard.ReadAll() if err != nil { logrus.WithError(err).Debug("failed to get value from clipboard") } case isInputPiped(): reader := bufio.NewReader(os.Stdin) expectedValue, err = reader.ReadString('\n') if err != nil { logrus.WithError(err).Debug("failed to get piped in value") } expectedValue = expectedValue[:len(expectedValue)-1] } if expectedValue == "" { fmt.Print("Enter expected value (it won't be displayed): ") byteValue, err := term.ReadPassword(int(os.Stdin.Fd())) if err != nil { return fmt.Errorf("error reading value: %w", err) } expectedValue = string(byteValue) } keeper, err := crypt.NewKeeper(cfg.Encryption.Type, cfg.Encryption.KeyPath) if err != nil { return err } decryptedValue, err := keeper.Decrypt(envKey, cipher) if err != nil { return fmt.Errorf("failed to encrypt value: %w", err) } if subtle.ConstantTimeCompare([]byte(decryptedValue), []byte(expectedValue)) == 1 { fmt.Print("equal") } else { fmt.Print("not-equal") } return nil }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.