From ff0e7feeee3f0787491267ad8ea7945e802e4a8d Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 19:14:21 +0200 Subject: [PATCH 01/18] feat(cli): CLI Keyring improvements --- cli/packages/cmd/vault.go | 47 +++++++++++++++++++++++++++-- cli/packages/models/cli.go | 9 +++--- cli/packages/util/config.go | 18 ++++++++--- cli/packages/util/constants.go | 4 +++ cli/packages/util/keyringwrapper.go | 35 ++++++++++++++++++--- cli/packages/util/vault.go | 6 ++-- 6 files changed, 101 insertions(+), 18 deletions(-) diff --git a/cli/packages/cmd/vault.go b/cli/packages/cmd/vault.go index 01bee147b..948667dc4 100644 --- a/cli/packages/cmd/vault.go +++ b/cli/packages/cmd/vault.go @@ -4,6 +4,7 @@ Copyright (c) 2023 Infisical Inc. package cmd import ( + "encoding/base64" "fmt" "strings" @@ -16,10 +17,49 @@ import ( var AvailableVaultsAndDescriptions = []string{"auto (automatically select native vault on system)", "file (encrypted file vault)"} var AvailableVaults = []string{"auto", "file"} +var vaultSetPassphraseCmd = &cobra.Command{ + Example: `infisical vault set-passphrase [your-passphrase]`, + Use: "set-passphrase [your-passphrase]", + Short: "Used to set the passphrase for the file vault", + DisableFlagsInUseLine: true, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 1 { + log.Error().Msgf("Please provide a passphrase to set for the file vault") + return + } + + passphrase := args[0] + + configFile, err := util.GetConfigFile() + if err != nil { + log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) + return + } + + if configFile.VaultBackendType != "file" { + log.Error().Msgf("You are not using file vault to store your login details. You can only set passphrase for file vault") + return + } + + // encode with base64 + encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(passphrase)) + configFile.VaultBackendPassphrase = encodedPassphrase + + err = util.WriteConfigFile(&configFile) + if err != nil { + log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) + return + } + + fmt.Printf("\nSuccessfully, set passphrase for file vault. You can now store your login details securely at rest\n") + }, +} + var vaultSetCmd = &cobra.Command{ - Example: `infisical vault set pass`, - Use: "set [vault-name]", - Short: "Used to set the vault backend to store your login details securely at rest", + Example: `infisical vault set [file|auto]`, + Use: "set [file|auto]", + Short: "Used to set the type of vault backend to store your login details securely at rest", DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { @@ -89,5 +129,6 @@ func printAvailableVaultBackends() { func init() { vaultCmd.AddCommand(vaultSetCmd) + vaultCmd.AddCommand(vaultSetPassphraseCmd) rootCmd.AddCommand(vaultCmd) } diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 4b02cb6f8..65404dafa 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -11,10 +11,11 @@ type UserCredentials struct { // The file struct for Infisical config file type ConfigFile struct { - LoggedInUserEmail string `json:"loggedInUserEmail"` - LoggedInUserDomain string `json:"LoggedInUserDomain,omitempty"` - LoggedInUsers []LoggedInUser `json:"loggedInUsers,omitempty"` - VaultBackendType string `json:"vaultBackendType,omitempty"` + LoggedInUserEmail string `json:"loggedInUserEmail"` + LoggedInUserDomain string `json:"LoggedInUserDomain,omitempty"` + LoggedInUsers []LoggedInUser `json:"loggedInUsers,omitempty"` + VaultBackendType string `json:"vaultBackendType,omitempty"` + VaultBackendPassphrase string `json:"vaultBackendPassphrase,omitempty"` } type LoggedInUser struct { diff --git a/cli/packages/util/config.go b/cli/packages/util/config.go index 55c9df1b0..02030e1fa 100644 --- a/cli/packages/util/config.go +++ b/cli/packages/util/config.go @@ -1,6 +1,7 @@ package util import ( + "encoding/base64" "encoding/json" "errors" "fmt" @@ -50,10 +51,11 @@ func WriteInitalConfig(userCredentials *models.UserCredentials) error { } configFile := models.ConfigFile{ - LoggedInUserEmail: userCredentials.Email, - LoggedInUserDomain: config.INFISICAL_URL, - LoggedInUsers: existingConfigFile.LoggedInUsers, - VaultBackendType: existingConfigFile.VaultBackendType, + LoggedInUserEmail: userCredentials.Email, + LoggedInUserDomain: config.INFISICAL_URL, + LoggedInUsers: existingConfigFile.LoggedInUsers, + VaultBackendType: existingConfigFile.VaultBackendType, + VaultBackendPassphrase: existingConfigFile.VaultBackendPassphrase, } configFileMarshalled, err := json.Marshal(configFile) @@ -215,6 +217,14 @@ func GetConfigFile() (models.ConfigFile, error) { return models.ConfigFile{}, err } + if configFile.VaultBackendPassphrase != "" { + decodedPassphrase, err := base64.StdEncoding.DecodeString(configFile.VaultBackendPassphrase) + if err != nil { + return models.ConfigFile{}, fmt.Errorf("GetConfigFile: Unable to decode base64 passphrase [err=%s]", err) + } + os.Setenv("INFISICAL_VAULT_FILE_PASSPHRASE", string(decodedPassphrase)) + } + return configFile, nil } diff --git a/cli/packages/util/constants.go b/cli/packages/util/constants.go index 5b0a93513..5cd66f50b 100644 --- a/cli/packages/util/constants.go +++ b/cli/packages/util/constants.go @@ -8,6 +8,10 @@ const ( INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json" INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN" INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME = "INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN" + INFISICAL_VAULT_FILE_PASSPHRASE_ENV_NAME = "INFISICAL_VAULT_FILE_PASSPHRASE" // This works because we've forked the keyring package and added support for this env variable. This explains why you won't find any occurrences of it in the CLI codebase. + + VAULT_BACKEND_AUTO_MODE = "auto" + VAULT_BACKEND_FILE_MODE = "file" // Universal Auth INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID" diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 3bf2dd6c4..4f8fd80d4 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -1,11 +1,18 @@ package util import ( + "strings" + + "github.com/fatih/color" "github.com/zalando/go-keyring" ) const MAIN_KEYRING_SERVICE = "infisical-cli" +func keyringNotConfigured(err error) bool { + return err != nil && strings.Contains(err.Error(), "was not provided by any .service files") +} + type TimeoutError struct { message string } @@ -20,16 +27,30 @@ func SetValueInKeyring(key, value string) error { PrintErrorAndExit(1, err, "Unable to get current vault. Tip: run [infisical rest] then try again") } - return keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) + err = keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) + + if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { + boldGreen := color.New(color.FgGreen).Add(color.Bold) + boldGreen.Printf("Warning: Fallback file keyring is being used") + err = keyring.Set(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key, value) + } + + return err } func GetValueInKeyring(key string) (string, error) { currentVaultBackend, err := GetCurrentVaultBackend() if err != nil { - PrintErrorAndExit(1, err, "Unable to get current vault. Tip: run [infisical rest] then try again") + PrintErrorAndExit(1, err, "Unable to get current vault. Tip: run [infisical reset] then try again") } - return keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + value, err := keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + + if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { + value, err = keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + } + return value, err + } func DeleteValueInKeyring(key string) error { @@ -38,5 +59,11 @@ func DeleteValueInKeyring(key string) error { return err } - return keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + err = keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + + if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { + err = keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + } + + return err } diff --git a/cli/packages/util/vault.go b/cli/packages/util/vault.go index 14d6d10d9..5907d93fc 100644 --- a/cli/packages/util/vault.go +++ b/cli/packages/util/vault.go @@ -11,11 +11,11 @@ func GetCurrentVaultBackend() (string, error) { } if configFile.VaultBackendType == "" { - return "auto", nil + return VAULT_BACKEND_AUTO_MODE, nil } - if configFile.VaultBackendType != "auto" && configFile.VaultBackendType != "file" { - return "auto", nil + if configFile.VaultBackendType != VAULT_BACKEND_AUTO_MODE && configFile.VaultBackendType != VAULT_BACKEND_FILE_MODE { + return VAULT_BACKEND_AUTO_MODE, nil } return configFile.VaultBackendType, nil From c3038e3ca17221062a216581aaf59dbf9cd7b6a9 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 22:47:07 +0200 Subject: [PATCH 02/18] docs: passphrase command --- docs/cli/commands/vault.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/vault.mdx b/docs/cli/commands/vault.mdx index 9030c580c..6ffc24b21 100644 --- a/docs/cli/commands/vault.mdx +++ b/docs/cli/commands/vault.mdx @@ -32,6 +32,6 @@ description: "Change the vault type in Infisical" To safeguard your login details when using the CLI, Infisical places them in a system vault or an encrypted text file, protected by a passphrase that only the user knows. -To avoid constantly entering your passphrase when using the `file` vault type, set the `INFISICAL_VAULT_FILE_PASSPHRASE` environment variable with your password in your shell +To avoid constantly entering your passphrase when using the `file` vault type, use the `infisical vault set file passphrase` CLI command to specify your password once. From e619cfa31328cf0d13c261c24419a6c115e2f97b Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 22:47:37 +0200 Subject: [PATCH 03/18] feat(cli): set persistent file vault password --- cli/packages/cmd/vault.go | 194 +++++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 68 deletions(-) diff --git a/cli/packages/cmd/vault.go b/cli/packages/cmd/vault.go index 948667dc4..187316a40 100644 --- a/cli/packages/cmd/vault.go +++ b/cli/packages/cmd/vault.go @@ -9,97 +9,88 @@ import ( "strings" "github.com/Infisical/infisical-merge/packages/util" + "github.com/manifoldco/promptui" "github.com/posthog/posthog-go" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) -var AvailableVaultsAndDescriptions = []string{"auto (automatically select native vault on system)", "file (encrypted file vault)"} -var AvailableVaults = []string{"auto", "file"} +type VaultBackendType struct { + Name string + Description string +} -var vaultSetPassphraseCmd = &cobra.Command{ - Example: `infisical vault set-passphrase [your-passphrase]`, - Use: "set-passphrase [your-passphrase]", - Short: "Used to set the passphrase for the file vault", - DisableFlagsInUseLine: true, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 1 { - log.Error().Msgf("Please provide a passphrase to set for the file vault") - return - } - - passphrase := args[0] - - configFile, err := util.GetConfigFile() - if err != nil { - log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) - return - } - - if configFile.VaultBackendType != "file" { - log.Error().Msgf("You are not using file vault to store your login details. You can only set passphrase for file vault") - return - } - - // encode with base64 - encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(passphrase)) - configFile.VaultBackendPassphrase = encodedPassphrase - - err = util.WriteConfigFile(&configFile) - if err != nil { - log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) - return - } - - fmt.Printf("\nSuccessfully, set passphrase for file vault. You can now store your login details securely at rest\n") +var AvailableVaults = []VaultBackendType{ + { + Name: "auto", + Description: "automatically select native vault on system", + }, + { + Name: "file", + Description: "encrypted file vault", }, } var vaultSetCmd = &cobra.Command{ - Example: `infisical vault set [file|auto]`, - Use: "set [file|auto]", + Example: `infisical vault set [file|auto] [option]`, + Use: "set [file|auto] [option]", Short: "Used to set the type of vault backend to store your login details securely at rest", + Long: "Used to set the type of vault backend to store your login details securely at rest", DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { - wantedVaultTypeName := args[0] - currentVaultBackend, err := util.GetCurrentVaultBackend() - if err != nil { - log.Error().Msgf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) - return - } - if wantedVaultTypeName == string(currentVaultBackend) { - log.Error().Msgf("You are already on vault backend [%s]", currentVaultBackend) - return - } + if len(args) >= 2 { + vaultType := args[0] + option := args[1] - if wantedVaultTypeName == "auto" || wantedVaultTypeName == "file" { - configFile, err := util.GetConfigFile() - if err != nil { - log.Error().Msgf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) + // Todo, add more vault types / configurations + if vaultType != util.VAULT_BACKEND_FILE_MODE { + log.Error().Msgf("No configuration options are available for vault type [%s]\n", vaultType) return } - configFile.VaultBackendType = wantedVaultTypeName // save selected vault - configFile.LoggedInUserEmail = "" // reset the logged in user to prompt them to re login + switch option { + case "passphrase": + { - err = util.WriteConfigFile(&configFile) - if err != nil { - log.Error().Msgf("Unable to set vault to [%s] because an error occurred when saving the config file [err=%s]", wantedVaultTypeName, err) - return + passphrasePrompt := promptui.Prompt{ + Label: "File vault passphrase", + } + + passphrase, err := passphrasePrompt.Run() + if err != nil { + log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) + return + } + + if passphrase == "" || len(passphrase) < 8 { + log.Error().Msgf("Passphrase must be at least 8 characters long") + return + } + setFileVaultPassphrase(passphrase) + } + default: + log.Error().Msgf("Unknown option [%s] for vault set command", option) } - fmt.Printf("\nSuccessfully, switched vault backend from [%s] to [%s]. Please login in again to store your login details in the new vault with [infisical login]\n", currentVaultBackend, wantedVaultTypeName) - - Telemetry.CaptureEvent("cli-command:vault set", posthog.NewProperties().Set("currentVault", currentVaultBackend).Set("wantedVault", wantedVaultTypeName).Set("version", util.CLI_VERSION)) - } else { - log.Error().Msgf("The requested vault type [%s] is not available on this system. Only the following vault backends are available for you system: %s", wantedVaultTypeName, strings.Join(AvailableVaults, ", ")) + return } + + fmt.Printf("Warning: This command has been deprecated. Please use 'infisical vault use [file|auto]' to select which vault to use.\n") + selectVaultTypeCmd(cmd, args) }, } +var vaultUseCmd = &cobra.Command{ + Example: `infisical vault use [file|auto]`, + Use: "use [file|auto]", + Short: "Used to set the type of vault backend to store your login details securely at rest", + DisableFlagsInUseLine: true, + Args: cobra.MinimumNArgs(1), + Run: selectVaultTypeCmd, +} + // runCmd represents the run command var vaultCmd = &cobra.Command{ Use: "vault", @@ -111,10 +102,35 @@ var vaultCmd = &cobra.Command{ }, } +func setFileVaultPassphrase(passphrase string) { + configFile, err := util.GetConfigFile() + if err != nil { + log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) + return + } + + if configFile.VaultBackendType != "file" { + log.Error().Msgf("You are not using file vault to store your login details. You can only set passphrase for file vault") + return + } + + // encode with base64 + encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(passphrase)) + configFile.VaultBackendPassphrase = encodedPassphrase + + err = util.WriteConfigFile(&configFile) + if err != nil { + log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) + return + } + + fmt.Printf("\nSuccessfully, set passphrase for file vault. You can now store your login details securely at rest\n") +} + func printAvailableVaultBackends() { fmt.Printf("Vaults are used to securely store your login details locally. Available vaults:") - for _, backend := range AvailableVaultsAndDescriptions { - fmt.Printf("\n- %s", backend) + for _, vaultType := range AvailableVaults { + fmt.Printf("\n- %s (%s)", vaultType.Name, vaultType.Description) } currentVaultBackend, err := util.GetCurrentVaultBackend() @@ -127,8 +143,50 @@ func printAvailableVaultBackends() { fmt.Printf("\n\nYou are currently using [%s] vault to store your login credentials\n", string(currentVaultBackend)) } +func selectVaultTypeCmd(cmd *cobra.Command, args []string) { + wantedVaultTypeName := args[0] + currentVaultBackend, err := util.GetCurrentVaultBackend() + if err != nil { + log.Error().Msgf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) + return + } + + if wantedVaultTypeName == string(currentVaultBackend) { + log.Error().Msgf("You are already on vault backend [%s]", currentVaultBackend) + return + } + + if wantedVaultTypeName == util.VAULT_BACKEND_AUTO_MODE || wantedVaultTypeName == util.VAULT_BACKEND_FILE_MODE { + configFile, err := util.GetConfigFile() + if err != nil { + log.Error().Msgf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) + return + } + + configFile.VaultBackendType = wantedVaultTypeName // save selected vault + configFile.LoggedInUserEmail = "" // reset the logged in user to prompt them to re login + + err = util.WriteConfigFile(&configFile) + if err != nil { + log.Error().Msgf("Unable to set vault to [%s] because an error occurred when saving the config file [err=%s]", wantedVaultTypeName, err) + return + } + + fmt.Printf("\nSuccessfully, switched vault backend from [%s] to [%s]. Please login in again to store your login details in the new vault with [infisical login]\n", currentVaultBackend, wantedVaultTypeName) + + Telemetry.CaptureEvent("cli-command:vault set", posthog.NewProperties().Set("currentVault", currentVaultBackend).Set("wantedVault", wantedVaultTypeName).Set("version", util.CLI_VERSION)) + } else { + var availableVaultsNames []string + for _, vault := range AvailableVaults { + availableVaultsNames = append(availableVaultsNames, vault.Name) + } + log.Error().Msgf("The requested vault type [%s] is not available on this system. Only the following vault backends are available for you system: %s", wantedVaultTypeName, strings.Join(availableVaultsNames, ", ")) + } +} + func init() { vaultCmd.AddCommand(vaultSetCmd) - vaultCmd.AddCommand(vaultSetPassphraseCmd) + vaultCmd.AddCommand(vaultUseCmd) + rootCmd.AddCommand(vaultCmd) } From 070eb2aacd75c80a39c85192075f0c0ebd2f343d Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 22:47:46 +0200 Subject: [PATCH 04/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 4f8fd80d4..62133616d 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -30,8 +30,10 @@ func SetValueInKeyring(key, value string) error { err = keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { - boldGreen := color.New(color.FgGreen).Add(color.Bold) - boldGreen.Printf("Warning: Fallback file keyring is being used") + boldYellow := color.New(color.FgYellow).Add(color.Bold) + boldYellow.Printf("Warning: Fallback file keyring is being used\n\n") + boldYellow.Printf("You can persist your file passphrase by running the following command:\n") + boldYellow.Printf("infisical vault set file passphrase \n\n") err = keyring.Set(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key, value) } From 2177ec6bcc4d3aa78d5ff403f2dd6a69e20545fb Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:04:34 +0200 Subject: [PATCH 05/18] Update vault.go --- cli/packages/cmd/vault.go | 54 +++++++++++---------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/cli/packages/cmd/vault.go b/cli/packages/cmd/vault.go index 187316a40..91f9313da 100644 --- a/cli/packages/cmd/vault.go +++ b/cli/packages/cmd/vault.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/Infisical/infisical-merge/packages/util" - "github.com/manifoldco/promptui" "github.com/posthog/posthog-go" "github.com/rs/zerolog/log" "github.com/spf13/cobra" @@ -23,7 +22,7 @@ type VaultBackendType struct { var AvailableVaults = []VaultBackendType{ { Name: "auto", - Description: "automatically select native vault on system", + Description: "automatically select the system keyring", }, { Name: "file", @@ -32,52 +31,26 @@ var AvailableVaults = []VaultBackendType{ } var vaultSetCmd = &cobra.Command{ - Example: `infisical vault set [file|auto] [option]`, + Example: `infisical vault set [file|auto]`, Use: "set [file|auto] [option]", - Short: "Used to set the type of vault backend to store your login details securely at rest", - Long: "Used to set the type of vault backend to store your login details securely at rest", + Short: "Used to set the type of vault backend to store sensitive data securely at rest", DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { - if len(args) >= 2 { - vaultType := args[0] - option := args[1] + vaultType := args[0] - // Todo, add more vault types / configurations - if vaultType != util.VAULT_BACKEND_FILE_MODE { - log.Error().Msgf("No configuration options are available for vault type [%s]\n", vaultType) - return - } - - switch option { - case "passphrase": - { - - passphrasePrompt := promptui.Prompt{ - Label: "File vault passphrase", - } - - passphrase, err := passphrasePrompt.Run() - if err != nil { - log.Error().Msgf("Unable to set passphrase for file vault because of [err=%s]", err) - return - } - - if passphrase == "" || len(passphrase) < 8 { - log.Error().Msgf("Passphrase must be at least 8 characters long") - return - } - setFileVaultPassphrase(passphrase) - } - default: - log.Error().Msgf("Unknown option [%s] for vault set command", option) - } + passphrase, err := cmd.Flags().GetString("passphrase") + if err != nil { + util.HandleError(err, "Unable to get passphrase flag") + } + if vaultType == util.VAULT_BACKEND_FILE_MODE && passphrase != "" { + setFileVaultPassphrase(passphrase) return } - fmt.Printf("Warning: This command has been deprecated. Please use 'infisical vault use [file|auto]' to select which vault to use.\n") + util.PrintWarning("This command has been deprecated. Please use 'infisical vault use [file|auto]' to select which vault to use.\n") selectVaultTypeCmd(cmd, args) }, } @@ -110,7 +83,7 @@ func setFileVaultPassphrase(passphrase string) { } if configFile.VaultBackendType != "file" { - log.Error().Msgf("You are not using file vault to store your login details. You can only set passphrase for file vault") + log.Error().Msgf("You are not using file vault to store your login details. You can only set passphrase for file vault. Use 'infisical vault use file' to switch to file vault") return } @@ -185,6 +158,9 @@ func selectVaultTypeCmd(cmd *cobra.Command, args []string) { } func init() { + + vaultSetCmd.Flags().StringP("passphrase", "p", "", "Set the passphrase for the file vault") + vaultCmd.AddCommand(vaultSetCmd) vaultCmd.AddCommand(vaultUseCmd) From 3d380710ee06e914b1ebb4611bec1938f9d6051a Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:10:42 +0200 Subject: [PATCH 06/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 62133616d..60da5f6c7 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -1,18 +1,11 @@ package util import ( - "strings" - - "github.com/fatih/color" "github.com/zalando/go-keyring" ) const MAIN_KEYRING_SERVICE = "infisical-cli" -func keyringNotConfigured(err error) bool { - return err != nil && strings.Contains(err.Error(), "was not provided by any .service files") -} - type TimeoutError struct { message string } @@ -29,11 +22,9 @@ func SetValueInKeyring(key, value string) error { err = keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) - if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { - boldYellow := color.New(color.FgYellow).Add(color.Bold) - boldYellow.Printf("Warning: Fallback file keyring is being used\n\n") - boldYellow.Printf("You can persist your file passphrase by running the following command:\n") - boldYellow.Printf("infisical vault set file passphrase \n\n") + if err != nil { + + PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file passphrase \n") err = keyring.Set(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key, value) } @@ -48,7 +39,7 @@ func GetValueInKeyring(key string) (string, error) { value, err := keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) - if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { + if err != nil { value, err = keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) } return value, err @@ -63,7 +54,7 @@ func DeleteValueInKeyring(key string) error { err = keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) - if err == keyring.ErrUnsupportedPlatform || keyringNotConfigured(err) { + if err != nil { err = keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) } From a9f04a3c1f4854463494dfb0b6647e13d40016b2 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:13:40 +0200 Subject: [PATCH 07/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 60da5f6c7..a2042e289 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -23,7 +23,6 @@ func SetValueInKeyring(key, value string) error { err = keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) if err != nil { - PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file passphrase \n") err = keyring.Set(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key, value) } @@ -40,7 +39,7 @@ func GetValueInKeyring(key string) (string, error) { value, err := keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) if err != nil { - value, err = keyring.Get(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + value, err = keyring.Get(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key) } return value, err @@ -55,7 +54,7 @@ func DeleteValueInKeyring(key string) error { err = keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) if err != nil { - err = keyring.Delete(currentVaultBackend, MAIN_KEYRING_SERVICE, key) + err = keyring.Delete(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key) } return err From e7a95e6af201d7b3c00cc406cd505d598b2d2be9 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:15:53 +0200 Subject: [PATCH 08/18] Update login.go --- cli/packages/cmd/login.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index 4717e0784..7996d0288 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -728,6 +728,8 @@ func askToPasteJwtToken(success chan models.UserCredentials, failure chan error) infisicalPastedToken := strings.TrimSpace(string(bytePassword)) + fmt.Printf("\n\nToken 1: %s\n", infisicalPastedToken) + userCredentials, err := decodePastedBase64Token(infisicalPastedToken) if err != nil { failure <- err @@ -742,6 +744,8 @@ func askToPasteJwtToken(success chan models.UserCredentials, failure chan error) isAuthenticated := api.CallIsAuthenticated(httpClient) if !isAuthenticated { + fmt.Printf("\n\nToken 2: %s\n", infisicalPastedToken) + fmt.Println("Invalid user credentials provided", err) failure <- err os.Exit(1) From 4249ec603070b08ce068e85c90c7bb3cad867eb3 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:21:31 +0200 Subject: [PATCH 09/18] Update login.go --- cli/packages/cmd/login.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index 7996d0288..4717e0784 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -728,8 +728,6 @@ func askToPasteJwtToken(success chan models.UserCredentials, failure chan error) infisicalPastedToken := strings.TrimSpace(string(bytePassword)) - fmt.Printf("\n\nToken 1: %s\n", infisicalPastedToken) - userCredentials, err := decodePastedBase64Token(infisicalPastedToken) if err != nil { failure <- err @@ -744,8 +742,6 @@ func askToPasteJwtToken(success chan models.UserCredentials, failure chan error) isAuthenticated := api.CallIsAuthenticated(httpClient) if !isAuthenticated { - fmt.Printf("\n\nToken 2: %s\n", infisicalPastedToken) - fmt.Println("Invalid user credentials provided", err) failure <- err os.Exit(1) From 91cee20cc8ebde7e9a135d996abf5ee0a159b075 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:21:38 +0200 Subject: [PATCH 10/18] Minor improvemnets --- cli/packages/cmd/vault.go | 7 +------ cli/packages/util/keyringwrapper.go | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/cli/packages/cmd/vault.go b/cli/packages/cmd/vault.go index 91f9313da..0e7dafe19 100644 --- a/cli/packages/cmd/vault.go +++ b/cli/packages/cmd/vault.go @@ -82,11 +82,6 @@ func setFileVaultPassphrase(passphrase string) { return } - if configFile.VaultBackendType != "file" { - log.Error().Msgf("You are not using file vault to store your login details. You can only set passphrase for file vault. Use 'infisical vault use file' to switch to file vault") - return - } - // encode with base64 encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(passphrase)) configFile.VaultBackendPassphrase = encodedPassphrase @@ -97,7 +92,7 @@ func setFileVaultPassphrase(passphrase string) { return } - fmt.Printf("\nSuccessfully, set passphrase for file vault. You can now store your login details securely at rest\n") + util.PrintSuccessMessage("\nSuccessfully, set passphrase for file vault.\n") } func printAvailableVaultBackends() { diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index a2042e289..a1b823765 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -23,7 +23,7 @@ func SetValueInKeyring(key, value string) error { err = keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) if err != nil { - PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file passphrase \n") + PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file --passphrase \n") err = keyring.Set(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key, value) } From 2b630f75aa0250e1a79d1ef9f0780e77311d8e80 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:31:02 +0200 Subject: [PATCH 11/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index a1b823765..66d60dac3 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -1,7 +1,12 @@ package util import ( + "encoding/base64" + "fmt" + "os" + "github.com/zalando/go-keyring" + "golang.org/x/term" ) const MAIN_KEYRING_SERVICE = "infisical-cli" @@ -23,7 +28,26 @@ func SetValueInKeyring(key, value string) error { err = keyring.Set(currentVaultBackend, MAIN_KEYRING_SERVICE, key, value) if err != nil { + configFile, _ := GetConfigFile() PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file --passphrase \n") + + if configFile.VaultBackendPassphrase == "" { + fmt.Print("\n\nEnter the passphrase to use for keyring encryption: ") + bytePassphrase, err := term.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + return err + } + encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(string(bytePassphrase))) + configFile.VaultBackendPassphrase = encodedPassphrase + err = WriteConfigFile(&configFile) + if err != nil { + return err + } + + // We call this function at last to trigger the environment variable to be set + GetConfigFile() + } + err = keyring.Set(VAULT_BACKEND_FILE_MODE, MAIN_KEYRING_SERVICE, key, value) } From 8777cfe6800281bcc160da550c1100f95ce8c11f Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:34:35 +0200 Subject: [PATCH 12/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 66d60dac3..a24a736c5 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -2,11 +2,9 @@ package util import ( "encoding/base64" - "fmt" - "os" + "github.com/manifoldco/promptui" "github.com/zalando/go-keyring" - "golang.org/x/term" ) const MAIN_KEYRING_SERVICE = "infisical-cli" @@ -32,12 +30,15 @@ func SetValueInKeyring(key, value string) error { PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file --passphrase \n") if configFile.VaultBackendPassphrase == "" { - fmt.Print("\n\nEnter the passphrase to use for keyring encryption: ") - bytePassphrase, err := term.ReadPassword(int(os.Stdin.Fd())) + passphrasePrompt := promptui.Prompt{ + Label: "\nEnter the passphrase to use for keyring encryption: ", + } + passphrase, err := passphrasePrompt.Run() if err != nil { return err } - encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(string(bytePassphrase))) + + encodedPassphrase := base64.StdEncoding.EncodeToString([]byte(passphrase)) configFile.VaultBackendPassphrase = encodedPassphrase err = WriteConfigFile(&configFile) if err != nil { From 879ef2c178e557545b56d54e58e1d37c314cf103 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 29 Jul 2024 12:37:58 +0200 Subject: [PATCH 13/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index a24a736c5..522e3aa8c 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -31,7 +31,7 @@ func SetValueInKeyring(key, value string) error { if configFile.VaultBackendPassphrase == "" { passphrasePrompt := promptui.Prompt{ - Label: "\nEnter the passphrase to use for keyring encryption: ", + Label: "Enter the passphrase to use for keyring encryption: ", } passphrase, err := passphrasePrompt.Run() if err != nil { From 85653a90d59a60a539068cfa59b21a098fa56c7f Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 29 Jul 2024 22:06:03 -0400 Subject: [PATCH 14/18] update phrasing --- cli/packages/util/keyringwrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 522e3aa8c..c1df66587 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -27,7 +27,7 @@ func SetValueInKeyring(key, value string) error { if err != nil { configFile, _ := GetConfigFile() - PrintWarning("Fallback file keyring is being used\n\nYou can persist your file passphrase by running the following command:\ninfisical vault set file --passphrase \n") + PrintWarning("System keyring could not be used, switching to `file` vault for local token storage\n\nYou can persist your file vault passphrase by running the following command:\ninfisical vault set file --passphrase \n") if configFile.VaultBackendPassphrase == "" { passphrasePrompt := promptui.Prompt{ From d5f4ce43761336b56eae215bf7046daad82d719e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 30 Jul 2024 10:22:15 +0200 Subject: [PATCH 15/18] Update vault.go --- cli/packages/cmd/vault.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/packages/cmd/vault.go b/cli/packages/cmd/vault.go index 0e7dafe19..4720e094e 100644 --- a/cli/packages/cmd/vault.go +++ b/cli/packages/cmd/vault.go @@ -31,9 +31,9 @@ var AvailableVaults = []VaultBackendType{ } var vaultSetCmd = &cobra.Command{ - Example: `infisical vault set [file|auto]`, - Use: "set [file|auto] [option]", - Short: "Used to set the type of vault backend to store sensitive data securely at rest", + Example: `infisical vault set file --passphrase `, + Use: "set [file|auto] [flags]", + Short: "Used to configure the vault backends", DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { @@ -58,7 +58,7 @@ var vaultSetCmd = &cobra.Command{ var vaultUseCmd = &cobra.Command{ Example: `infisical vault use [file|auto]`, Use: "use [file|auto]", - Short: "Used to set the type of vault backend to store your login details securely at rest", + Short: "Used to select the the type of vault backend to store sensitive data securely at rest", DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Run: selectVaultTypeCmd, From 02e8f20cbfa5205e6f8276d9eb6f496b54a1fd90 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 31 Jul 2024 03:14:06 +0000 Subject: [PATCH 16/18] remove extra : --- cli/packages/util/keyringwrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index c1df66587..5b6de96bc 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -31,7 +31,7 @@ func SetValueInKeyring(key, value string) error { if configFile.VaultBackendPassphrase == "" { passphrasePrompt := promptui.Prompt{ - Label: "Enter the passphrase to use for keyring encryption: ", + Label: "Enter the passphrase to use for keyring encryption", } passphrase, err := passphrasePrompt.Run() if err != nil { From 891cb06de09f8b97e5c06d010d74c6b6ee59c66b Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Wed, 31 Jul 2024 16:55:53 +0200 Subject: [PATCH 17/18] Update keyringwrapper.go --- cli/packages/util/keyringwrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/packages/util/keyringwrapper.go b/cli/packages/util/keyringwrapper.go index 5b6de96bc..cadb72ebd 100644 --- a/cli/packages/util/keyringwrapper.go +++ b/cli/packages/util/keyringwrapper.go @@ -27,9 +27,9 @@ func SetValueInKeyring(key, value string) error { if err != nil { configFile, _ := GetConfigFile() - PrintWarning("System keyring could not be used, switching to `file` vault for local token storage\n\nYou can persist your file vault passphrase by running the following command:\ninfisical vault set file --passphrase \n") if configFile.VaultBackendPassphrase == "" { + PrintWarning("System keyring could not be used, falling back to `file` vault for sensitive data storage.") passphrasePrompt := promptui.Prompt{ Label: "Enter the passphrase to use for keyring encryption", } From c8b93e44673f786f35dd2dd5632bebeefa512314 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 5 Aug 2024 13:11:40 -0400 Subject: [PATCH 18/18] Update doc to show correct command --- docs/cli/commands/vault.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/vault.mdx b/docs/cli/commands/vault.mdx index 6ffc24b21..803af127f 100644 --- a/docs/cli/commands/vault.mdx +++ b/docs/cli/commands/vault.mdx @@ -32,6 +32,6 @@ description: "Change the vault type in Infisical" To safeguard your login details when using the CLI, Infisical places them in a system vault or an encrypted text file, protected by a passphrase that only the user knows. -To avoid constantly entering your passphrase when using the `file` vault type, use the `infisical vault set file passphrase` CLI command to specify your password once. +To avoid constantly entering your passphrase when using the `file` vault type, use the `infisical vault set file --passphrase ` CLI command to specify your password once.