mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat(cli): CLI Keyring improvements
This commit is contained in:
@@ -4,6 +4,7 @@ Copyright (c) 2023 Infisical Inc.
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -16,10 +17,49 @@ import (
|
|||||||
var AvailableVaultsAndDescriptions = []string{"auto (automatically select native vault on system)", "file (encrypted file vault)"}
|
var AvailableVaultsAndDescriptions = []string{"auto (automatically select native vault on system)", "file (encrypted file vault)"}
|
||||||
var AvailableVaults = []string{"auto", "file"}
|
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{
|
var vaultSetCmd = &cobra.Command{
|
||||||
Example: `infisical vault set pass`,
|
Example: `infisical vault set [file|auto]`,
|
||||||
Use: "set [vault-name]",
|
Use: "set [file|auto]",
|
||||||
Short: "Used to set the vault backend to store your login details securely at rest",
|
Short: "Used to set the type of vault backend to store your login details securely at rest",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@@ -89,5 +129,6 @@ func printAvailableVaultBackends() {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vaultCmd.AddCommand(vaultSetCmd)
|
vaultCmd.AddCommand(vaultSetCmd)
|
||||||
|
vaultCmd.AddCommand(vaultSetPassphraseCmd)
|
||||||
rootCmd.AddCommand(vaultCmd)
|
rootCmd.AddCommand(vaultCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ type UserCredentials struct {
|
|||||||
|
|
||||||
// The file struct for Infisical config file
|
// The file struct for Infisical config file
|
||||||
type ConfigFile struct {
|
type ConfigFile struct {
|
||||||
LoggedInUserEmail string `json:"loggedInUserEmail"`
|
LoggedInUserEmail string `json:"loggedInUserEmail"`
|
||||||
LoggedInUserDomain string `json:"LoggedInUserDomain,omitempty"`
|
LoggedInUserDomain string `json:"LoggedInUserDomain,omitempty"`
|
||||||
LoggedInUsers []LoggedInUser `json:"loggedInUsers,omitempty"`
|
LoggedInUsers []LoggedInUser `json:"loggedInUsers,omitempty"`
|
||||||
VaultBackendType string `json:"vaultBackendType,omitempty"`
|
VaultBackendType string `json:"vaultBackendType,omitempty"`
|
||||||
|
VaultBackendPassphrase string `json:"vaultBackendPassphrase,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoggedInUser struct {
|
type LoggedInUser struct {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -50,10 +51,11 @@ func WriteInitalConfig(userCredentials *models.UserCredentials) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configFile := models.ConfigFile{
|
configFile := models.ConfigFile{
|
||||||
LoggedInUserEmail: userCredentials.Email,
|
LoggedInUserEmail: userCredentials.Email,
|
||||||
LoggedInUserDomain: config.INFISICAL_URL,
|
LoggedInUserDomain: config.INFISICAL_URL,
|
||||||
LoggedInUsers: existingConfigFile.LoggedInUsers,
|
LoggedInUsers: existingConfigFile.LoggedInUsers,
|
||||||
VaultBackendType: existingConfigFile.VaultBackendType,
|
VaultBackendType: existingConfigFile.VaultBackendType,
|
||||||
|
VaultBackendPassphrase: existingConfigFile.VaultBackendPassphrase,
|
||||||
}
|
}
|
||||||
|
|
||||||
configFileMarshalled, err := json.Marshal(configFile)
|
configFileMarshalled, err := json.Marshal(configFile)
|
||||||
@@ -215,6 +217,14 @@ func GetConfigFile() (models.ConfigFile, error) {
|
|||||||
return models.ConfigFile{}, err
|
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
|
return configFile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ const (
|
|||||||
INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json"
|
INFISICAL_WORKSPACE_CONFIG_FILE_NAME = ".infisical.json"
|
||||||
INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN"
|
INFISICAL_TOKEN_NAME = "INFISICAL_TOKEN"
|
||||||
INFISICAL_UNIVERSAL_AUTH_ACCESS_TOKEN_NAME = "INFISICAL_UNIVERSAL_AUTH_ACCESS_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
|
// Universal Auth
|
||||||
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID"
|
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID"
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
"github.com/zalando/go-keyring"
|
"github.com/zalando/go-keyring"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MAIN_KEYRING_SERVICE = "infisical-cli"
|
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 {
|
type TimeoutError struct {
|
||||||
message string
|
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")
|
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) {
|
func GetValueInKeyring(key string) (string, error) {
|
||||||
currentVaultBackend, err := GetCurrentVaultBackend()
|
currentVaultBackend, err := GetCurrentVaultBackend()
|
||||||
if err != nil {
|
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 {
|
func DeleteValueInKeyring(key string) error {
|
||||||
@@ -38,5 +59,11 @@ func DeleteValueInKeyring(key string) error {
|
|||||||
return err
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ func GetCurrentVaultBackend() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if configFile.VaultBackendType == "" {
|
if configFile.VaultBackendType == "" {
|
||||||
return "auto", nil
|
return VAULT_BACKEND_AUTO_MODE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if configFile.VaultBackendType != "auto" && configFile.VaultBackendType != "file" {
|
if configFile.VaultBackendType != VAULT_BACKEND_AUTO_MODE && configFile.VaultBackendType != VAULT_BACKEND_FILE_MODE {
|
||||||
return "auto", nil
|
return VAULT_BACKEND_AUTO_MODE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return configFile.VaultBackendType, nil
|
return configFile.VaultBackendType, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user