mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
fix: resolved keyring dataset too big by keeping only the encryption key
This commit is contained in:
@@ -38,7 +38,9 @@ const (
|
||||
SERVICE_TOKEN_IDENTIFIER = "service-token"
|
||||
UNIVERSAL_AUTH_TOKEN_IDENTIFIER = "universal-auth-token"
|
||||
|
||||
INFISICAL_BACKUP_SECRET = "infisical-backup-secrets"
|
||||
// akhilmhdh: @depreciated remove in version v0.30
|
||||
INFISICAL_BACKUP_SECRET = "infisical-backup-secrets"
|
||||
INFISICAL_BACKUP_SECRET_ENCRYPTION_KEY = "infisical-backup-secret-encryption-key"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
@@ -285,18 +286,25 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectCo
|
||||
log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", err)
|
||||
|
||||
if err == nil {
|
||||
WriteBackupSecrets(infisicalDotJson.WorkspaceId, params.Environment, params.SecretsPath, res.Secrets)
|
||||
backupEncryptionKey, err := GetBackupEncryptionKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
WriteBackupSecrets(infisicalDotJson.WorkspaceId, params.Environment, params.SecretsPath, backupEncryptionKey, res.Secrets)
|
||||
}
|
||||
|
||||
secretsToReturn = res.Secrets
|
||||
errorToReturn = err
|
||||
// only attempt to serve cached secrets if no internet connection and if at least one secret cached
|
||||
if !isConnected {
|
||||
backedSecrets, err := ReadBackupSecrets(infisicalDotJson.WorkspaceId, params.Environment, params.SecretsPath)
|
||||
if len(backedSecrets) > 0 {
|
||||
PrintWarning("Unable to fetch latest secret(s) due to connection error, serving secrets from last successful fetch. For more info, run with --debug")
|
||||
secretsToReturn = backedSecrets
|
||||
errorToReturn = err
|
||||
backupEncryptionKey, _ := GetBackupEncryptionKey()
|
||||
if backupEncryptionKey != nil {
|
||||
backedSecrets, err := ReadBackupSecrets(infisicalDotJson.WorkspaceId, params.Environment, params.SecretsPath, backupEncryptionKey)
|
||||
if len(backedSecrets) > 0 {
|
||||
PrintWarning("Unable to fetch latest secret(s) due to connection error, serving secrets from last successful fetch. For more info, run with --debug")
|
||||
secretsToReturn = backedSecrets
|
||||
errorToReturn = err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,71 +484,90 @@ func OverrideSecrets(secrets []models.SingleEnvironmentVariable, secretType stri
|
||||
return secretsToReturn
|
||||
}
|
||||
|
||||
func WriteBackupSecrets(workspace string, environment string, secretsPath string, secrets []models.SingleEnvironmentVariable) error {
|
||||
var backedUpSecrets []models.BackupSecretKeyRing
|
||||
secretValueInKeyRing, err := GetValueInKeyring(INFISICAL_BACKUP_SECRET)
|
||||
func GetBackupEncryptionKey() ([]byte, error) {
|
||||
encryptionKey, err := GetValueInKeyring(INFISICAL_BACKUP_SECRET_ENCRYPTION_KEY)
|
||||
if err != nil {
|
||||
if err == keyring.ErrUnsupportedPlatform {
|
||||
return errors.New("your OS does not support keyring. Consider using a service token https://infisical.com/docs/documentation/platform/token")
|
||||
} else if err != keyring.ErrNotFound {
|
||||
return fmt.Errorf("something went wrong, failed to retrieve value from system keyring [error=%v]", err)
|
||||
return nil, errors.New("your OS does not support keyring. Consider using a service token https://infisical.com/docs/documentation/platform/token")
|
||||
} else if err == keyring.ErrNotFound {
|
||||
// generate a new key
|
||||
randomizedKey := make([]byte, 16)
|
||||
rand.Read(randomizedKey)
|
||||
encryptionKey = hex.EncodeToString(randomizedKey)
|
||||
if err := SetValueInKeyring(INFISICAL_BACKUP_SECRET_ENCRYPTION_KEY, encryptionKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(encryptionKey), nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("something went wrong, failed to retrieve value from system keyring [error=%v]", err)
|
||||
}
|
||||
}
|
||||
_ = json.Unmarshal([]byte(secretValueInKeyRing), &backedUpSecrets)
|
||||
return []byte(encryptionKey), nil
|
||||
}
|
||||
|
||||
backedUpSecrets = slices.DeleteFunc(backedUpSecrets, func(e models.BackupSecretKeyRing) bool {
|
||||
return e.SecretPath == secretsPath && e.ProjectID == workspace && e.Environment == environment
|
||||
})
|
||||
newBackupSecret := models.BackupSecretKeyRing{
|
||||
ProjectID: workspace,
|
||||
Environment: environment,
|
||||
SecretPath: secretsPath,
|
||||
Secrets: secrets,
|
||||
}
|
||||
backedUpSecrets = append(backedUpSecrets, newBackupSecret)
|
||||
func WriteBackupSecrets(workspace string, environment string, secretsPath string, encryptionKey []byte, secrets []models.SingleEnvironmentVariable) error {
|
||||
formattedPath := strings.ReplaceAll(secretsPath, "/", "-")
|
||||
fileName := fmt.Sprintf("project_secrets_%s_%s_%s.json", workspace, environment, formattedPath)
|
||||
secrets_backup_folder_name := "secrets-backup"
|
||||
|
||||
listOfSecretsMarshalled, err := json.Marshal(backedUpSecrets)
|
||||
_, fullConfigFileDirPath, err := GetFullConfigFilePath()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("WriteBackupSecrets: unable to get full config folder path [err=%s]", err)
|
||||
}
|
||||
|
||||
err = SetValueInKeyring(INFISICAL_BACKUP_SECRET, string(listOfSecretsMarshalled))
|
||||
// create secrets backup directory
|
||||
fullPathToSecretsBackupFolder := fmt.Sprintf("%s/%s", fullConfigFileDirPath, secrets_backup_folder_name)
|
||||
if _, err := os.Stat(fullPathToSecretsBackupFolder); errors.Is(err, os.ErrNotExist) {
|
||||
err := os.Mkdir(fullPathToSecretsBackupFolder, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
marshaledSecrets, _ := json.Marshal(secrets)
|
||||
result, err := crypto.EncryptSymmetric(marshaledSecrets, encryptionKey)
|
||||
listOfSecretsMarshalled, _ := json.Marshal(result)
|
||||
err = os.WriteFile(fmt.Sprintf("%s/%s", fullPathToSecretsBackupFolder, fileName), listOfSecretsMarshalled, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("StoreUserCredsInKeyRing: unable to store user credentials because [err=%s]", err)
|
||||
return fmt.Errorf("WriteBackupSecrets: Unable to write backup secrets to file [err=%s]", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadBackupSecrets(workspace string, environment string, secretsPath string) ([]models.SingleEnvironmentVariable, error) {
|
||||
secretValueInKeyRing, err := GetValueInKeyring(INFISICAL_BACKUP_SECRET)
|
||||
func ReadBackupSecrets(workspace string, environment string, secretsPath string, encryptionKey []byte) ([]models.SingleEnvironmentVariable, error) {
|
||||
formattedPath := strings.ReplaceAll(secretsPath, "/", "-")
|
||||
fileName := fmt.Sprintf("project_secrets_%s_%s_%s.json", workspace, environment, formattedPath)
|
||||
secrets_backup_folder_name := "secrets-backup"
|
||||
|
||||
_, fullConfigFileDirPath, err := GetFullConfigFilePath()
|
||||
if err != nil {
|
||||
if err == keyring.ErrUnsupportedPlatform {
|
||||
return nil, errors.New("your OS does not support keyring. Consider using a service token https://infisical.com/docs/documentation/platform/token")
|
||||
} else if err == keyring.ErrNotFound {
|
||||
return nil, errors.New("credentials not found in system keyring")
|
||||
} else {
|
||||
return nil, fmt.Errorf("something went wrong, failed to retrieve value from system keyring [error=%v]", err)
|
||||
}
|
||||
return nil, fmt.Errorf("ReadBackupSecrets: unable to write config file because an error occurred when getting config file path [err=%s]", err)
|
||||
}
|
||||
|
||||
var backedUpSecrets []models.BackupSecretKeyRing
|
||||
err = json.Unmarshal([]byte(secretValueInKeyRing), &backedUpSecrets)
|
||||
fullPathToSecretsBackupFolder := fmt.Sprintf("%s/%s", fullConfigFileDirPath, secrets_backup_folder_name)
|
||||
if _, err := os.Stat(fullPathToSecretsBackupFolder); errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
encryptedBackupSecretsFilePath := fmt.Sprintf("%s/%s", fullPathToSecretsBackupFolder, fileName)
|
||||
|
||||
encryptedBackupSecretsAsBytes, err := os.ReadFile(encryptedBackupSecretsFilePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getUserCredsFromKeyRing: Something went wrong when unmarshalling user creds [err=%s]", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, backupSecret := range backedUpSecrets {
|
||||
if backupSecret.Environment == environment && backupSecret.ProjectID == workspace && backupSecret.SecretPath == secretsPath {
|
||||
return backupSecret.Secrets, nil
|
||||
}
|
||||
}
|
||||
var encryptedBackUpSecrets models.SymmetricEncryptionResult
|
||||
_ = json.Unmarshal(encryptedBackupSecretsAsBytes, &encryptedBackUpSecrets)
|
||||
result, err := crypto.DecryptSymmetric(encryptionKey, encryptedBackUpSecrets.CipherText, encryptedBackUpSecrets.AuthTag, encryptedBackUpSecrets.Nonce)
|
||||
|
||||
var plainTextSecrets []models.SingleEnvironmentVariable
|
||||
_ = json.Unmarshal(result, &plainTextSecrets)
|
||||
|
||||
return plainTextSecrets, nil
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func DeleteBackupSecrets() error {
|
||||
// keeping this logic for now. Need to remove it later as more users migrate keyring would be used and this folder will be removed completely by then
|
||||
secrets_backup_folder_name := "secrets-backup"
|
||||
|
||||
_, fullConfigFileDirPath, err := GetFullConfigFilePath()
|
||||
@@ -549,8 +576,8 @@ func DeleteBackupSecrets() error {
|
||||
}
|
||||
|
||||
fullPathToSecretsBackupFolder := fmt.Sprintf("%s/%s", fullConfigFileDirPath, secrets_backup_folder_name)
|
||||
|
||||
DeleteValueInKeyring(INFISICAL_BACKUP_SECRET)
|
||||
DeleteValueInKeyring(INFISICAL_BACKUP_SECRET_ENCRYPTION_KEY)
|
||||
|
||||
return os.RemoveAll(fullPathToSecretsBackupFolder)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user