mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 05:27:52 +00:00
Feat: --watch flag for watching for secret changes
This commit is contained in:
+303
-110
@@ -4,6 +4,7 @@ Copyright (c) 2023 Infisical Inc.
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Infisical/infisical-merge/packages/models"
|
"github.com/Infisical/infisical-merge/packages/models"
|
||||||
"github.com/Infisical/infisical-merge/packages/util"
|
"github.com/Infisical/infisical-merge/packages/util"
|
||||||
@@ -77,6 +79,11 @@ var runCmd = &cobra.Command{
|
|||||||
util.HandleError(err, "Unable to parse flag")
|
util.HandleError(err, "Unable to parse flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hotReloadEnabled, err := cmd.Flags().GetBool("watch")
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Unable to parse flag")
|
||||||
|
}
|
||||||
|
|
||||||
secretOverriding, err := cmd.Flags().GetBool("secret-overriding")
|
secretOverriding, err := cmd.Flags().GetBool("secret-overriding")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err, "Unable to parse flag")
|
util.HandleError(err, "Unable to parse flag")
|
||||||
@@ -116,68 +123,16 @@ var runCmd = &cobra.Command{
|
|||||||
Recursive: recursive,
|
Recursive: recursive,
|
||||||
}
|
}
|
||||||
|
|
||||||
if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER {
|
env, initialETag, err := createInjectableEnvironment(request, projectConfigDir, secretOverriding, shouldExpandSecrets, token)
|
||||||
request.InfisicalToken = token.Token
|
|
||||||
} else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER {
|
|
||||||
request.UniversalAuthAccessToken = token.Token
|
|
||||||
}
|
|
||||||
|
|
||||||
secrets, err := util.GetAllEnvironmentVariables(request, projectConfigDir)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid")
|
util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid")
|
||||||
}
|
}
|
||||||
|
|
||||||
if secretOverriding {
|
|
||||||
secrets = util.OverrideSecrets(secrets, util.SECRET_TYPE_PERSONAL)
|
|
||||||
} else {
|
|
||||||
secrets = util.OverrideSecrets(secrets, util.SECRET_TYPE_SHARED)
|
|
||||||
}
|
|
||||||
|
|
||||||
if shouldExpandSecrets {
|
|
||||||
|
|
||||||
authParams := models.ExpandSecretsAuthentication{}
|
|
||||||
|
|
||||||
if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER {
|
|
||||||
authParams.InfisicalToken = token.Token
|
|
||||||
} else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER {
|
|
||||||
authParams.UniversalAuthAccessToken = token.Token
|
|
||||||
}
|
|
||||||
|
|
||||||
secrets = util.ExpandSecrets(secrets, authParams, projectConfigDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
secretsByKey := getSecretsByKeys(secrets)
|
|
||||||
environmentVariables := make(map[string]string)
|
|
||||||
|
|
||||||
// add all existing environment vars
|
|
||||||
for _, s := range os.Environ() {
|
|
||||||
kv := strings.SplitN(s, "=", 2)
|
|
||||||
key := kv[0]
|
|
||||||
value := kv[1]
|
|
||||||
environmentVariables[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if there are any reserved key words in secrets to inject
|
|
||||||
filterReservedEnvVars(secretsByKey)
|
|
||||||
|
|
||||||
// now add infisical secrets
|
|
||||||
for k, v := range secretsByKey {
|
|
||||||
environmentVariables[k] = v.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// turn it back into a list of envs
|
|
||||||
var env []string
|
|
||||||
for key, value := range environmentVariables {
|
|
||||||
s := key + "=" + value
|
|
||||||
env = append(env, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug().Msgf("injecting the following environment variables into shell: %v", env)
|
log.Debug().Msgf("injecting the following environment variables into shell: %v", env)
|
||||||
|
|
||||||
Telemetry.CaptureEvent("cli-command:run",
|
Telemetry.CaptureEvent("cli-command:run",
|
||||||
posthog.NewProperties().
|
posthog.NewProperties().
|
||||||
Set("secretsCount", len(secrets)).
|
Set("secretsCount", len(env)).
|
||||||
Set("environment", environmentName).
|
Set("environment", environmentName).
|
||||||
Set("isUsingServiceToken", token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER).
|
Set("isUsingServiceToken", token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER).
|
||||||
Set("isUsingUniversalAuthToken", token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER).
|
Set("isUsingUniversalAuthToken", token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER).
|
||||||
@@ -185,21 +140,23 @@ var runCmd = &cobra.Command{
|
|||||||
Set("multi-command", cmd.Flag("command").Value.String()).
|
Set("multi-command", cmd.Flag("command").Value.String()).
|
||||||
Set("version", util.CLI_VERSION))
|
Set("version", util.CLI_VERSION))
|
||||||
|
|
||||||
|
hotReloadParameters := models.ExecuteCommandHotReloadParameters{
|
||||||
|
Enabled: hotReloadEnabled,
|
||||||
|
GetSecretsDetails: request,
|
||||||
|
ProjectConfigDir: projectConfigDir,
|
||||||
|
SecretOverriding: secretOverriding,
|
||||||
|
ExpandSecrets: shouldExpandSecrets,
|
||||||
|
InitialETag: initialETag,
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Flags().Changed("command") {
|
if cmd.Flags().Changed("command") {
|
||||||
command := cmd.Flag("command").Value.String()
|
command := cmd.Flag("command").Value.String()
|
||||||
|
|
||||||
err = executeMultipleCommandWithEnvs(command, len(secretsByKey), env)
|
executeMultipleCommandWithEnvs(command, len(env), env, hotReloadParameters, token)
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
err = executeSingleCommandWithEnvs(args, len(secretsByKey), env)
|
executeSingleCommandWithEnvs(args, len(env), env, hotReloadParameters, token)
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -244,6 +201,7 @@ func init() {
|
|||||||
runCmd.Flags().Bool("include-imports", true, "Import linked secrets ")
|
runCmd.Flags().Bool("include-imports", true, "Import linked secrets ")
|
||||||
runCmd.Flags().Bool("recursive", false, "Fetch secrets from all sub-folders")
|
runCmd.Flags().Bool("recursive", false, "Fetch secrets from all sub-folders")
|
||||||
runCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets")
|
runCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets")
|
||||||
|
runCmd.Flags().Bool("watch", false, "Enable reload of application when secrets change")
|
||||||
runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")")
|
runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")")
|
||||||
runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ")
|
runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ")
|
||||||
runCmd.Flags().String("path", "/", "get secrets within a folder path")
|
runCmd.Flags().String("path", "/", "get secrets within a folder path")
|
||||||
@@ -251,66 +209,301 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Will execute a single command and pass in the given secrets into the process
|
// Will execute a single command and pass in the given secrets into the process
|
||||||
func executeSingleCommandWithEnvs(args []string, secretsCount int, env []string) error {
|
func executeSingleCommandWithEnvs(args []string, secretsCount int, env []string, reloadParameters models.ExecuteCommandHotReloadParameters, token *models.TokenDetails) {
|
||||||
command := args[0]
|
ctx, cancelCtx := context.WithCancel(context.Background())
|
||||||
argsForCommand := args[1:]
|
defer cancelCtx()
|
||||||
|
|
||||||
log.Info().Msgf(color.GreenString("Injecting %v Infisical secrets into your application process", secretsCount))
|
// Set up signal handling
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
cmd := exec.Command(command, argsForCommand...)
|
if reloadParameters.Enabled {
|
||||||
cmd.Stdin = os.Stdin
|
log.Info().Msgf(color.YellowString("[HOT RELOAD] Watching for secret changes..."))
|
||||||
cmd.Stdout = os.Stdout
|
go func() {
|
||||||
cmd.Stderr = os.Stderr
|
<-sigChan
|
||||||
cmd.Env = env
|
log.Info().Msg("Received termination signal. Cleaning up...")
|
||||||
|
cancelCtx()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
return execCmd(cmd)
|
var cmd *exec.Cmd
|
||||||
}
|
|
||||||
|
|
||||||
func executeMultipleCommandWithEnvs(fullCommand string, secretsCount int, env []string) error {
|
startCmd := func() error {
|
||||||
shell := [2]string{"sh", "-c"}
|
command := args[0]
|
||||||
if runtime.GOOS == "windows" {
|
argsForCommand := args[1:]
|
||||||
shell = [2]string{"cmd", "/C"}
|
|
||||||
} else {
|
log.Info().Msgf(color.GreenString("Injecting %v Infisical secrets into your application process", secretsCount))
|
||||||
currentShell := os.Getenv("SHELL")
|
|
||||||
if currentShell != "" {
|
cmd := exec.Command(command, argsForCommand...)
|
||||||
shell[0] = currentShell
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Env = env
|
||||||
|
|
||||||
|
if reloadParameters.Enabled {
|
||||||
|
go func() {
|
||||||
|
execCommandWithReload(cmd, cancelCtx)
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
return execCmd(cmd)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(shell[0], shell[1], fullCommand)
|
err := startCmd() // Initial command start, if no --watch flag is passed, it will work like in old versions of infisical CLI.
|
||||||
cmd.Stdin = os.Stdin
|
if err != nil {
|
||||||
cmd.Stdout = os.Stdout
|
util.HandleError(err, "Failed to start command")
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Env = env
|
|
||||||
|
|
||||||
log.Info().Msgf(color.GreenString("Injecting %v Infisical secrets into your application process", secretsCount))
|
|
||||||
log.Debug().Msgf("executing command: %s %s %s \n", shell[0], shell[1], fullCommand)
|
|
||||||
|
|
||||||
return execCmd(cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credit: inspired by AWS Valut
|
|
||||||
func execCmd(cmd *exec.Cmd) error {
|
|
||||||
sigChannel := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigChannel)
|
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
// This part is only relevant when the --watch flag is passed, as it's purpose is to solely watch for changes and manage process reloads.
|
||||||
|
if reloadParameters.Enabled {
|
||||||
|
ticker := time.NewTicker(10 * time.Second) // We check every 10 seconds for secret changes
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
sig := <-sigChannel
|
select {
|
||||||
_ = cmd.Process.Signal(sig) // process all sigs
|
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Debug().Msg("Exiting hot reload...")
|
||||||
|
handleCommandTermination(cmd, cancelCtx)
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
log.Debug().Msg("Checking for environment updates...")
|
||||||
|
newEnv, newEtag, err := createInjectableEnvironment(
|
||||||
|
reloadParameters.GetSecretsDetails,
|
||||||
|
reloadParameters.ProjectConfigDir,
|
||||||
|
reloadParameters.SecretOverriding,
|
||||||
|
reloadParameters.ExpandSecrets,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to fetch new secrets")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if newEtag != reloadParameters.InitialETag {
|
||||||
|
log.Info().Msg("[HOT RELOAD] Environment changed. Reloading application...")
|
||||||
|
reloadParameters.InitialETag = newEtag
|
||||||
|
env = newEnv
|
||||||
|
secretsCount = len(newEnv)
|
||||||
|
startCmd() // Restart the command with new environment
|
||||||
|
} else {
|
||||||
|
log.Debug().Msg("Not reloading because environments are identical")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
|
}
|
||||||
|
func executeMultipleCommandWithEnvs(fullCommand string, secretsCount int, env []string, reloadParameters models.ExecuteCommandHotReloadParameters, token *models.TokenDetails) {
|
||||||
|
ctx, cancelCtx := context.WithCancel(context.Background())
|
||||||
|
defer cancelCtx()
|
||||||
|
|
||||||
|
// Set up signal handling
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
if reloadParameters.Enabled {
|
||||||
|
log.Info().Msgf(color.HiMagentaString("[HOT RELOAD] Watching for secret changes..."))
|
||||||
|
go func() {
|
||||||
|
<-sigChan
|
||||||
|
log.Info().Msg(color.HiMagentaString("Received termination signal. Cleaning up..."))
|
||||||
|
cancelCtx()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
|
||||||
|
startCmd := func() error {
|
||||||
|
shell := [2]string{"sh", "-c"}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
shell = [2]string{"cmd", "/C"}
|
||||||
|
} else {
|
||||||
|
currentShell := os.Getenv("SHELL")
|
||||||
|
if currentShell != "" {
|
||||||
|
shell[0] = currentShell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = exec.CommandContext(ctx, shell[0], shell[1], fullCommand)
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Env = env
|
||||||
|
|
||||||
|
log.Info().Msgf(color.GreenString("Injecting %v Infisical secrets into your application process", secretsCount))
|
||||||
|
log.Debug().Msgf("executing command: %s %s %s \n", shell[0], shell[1], fullCommand)
|
||||||
|
|
||||||
|
if reloadParameters.Enabled {
|
||||||
|
go func() {
|
||||||
|
execCommandWithReload(cmd, cancelCtx)
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
return execCmd(cmd)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := startCmd() // Initial command start, if no --watch flag is passed, it will work like in old versions of infisical CLI.
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Failed to start command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This part is only relevant when the --watch flag is passed, as it's purpose is to solely watch for changes and manage process reloads.
|
||||||
|
if reloadParameters.Enabled {
|
||||||
|
ticker := time.NewTicker(10 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Info().Msg(color.HiMagentaString("[HOT RELOAD] Exiting..."))
|
||||||
|
handleCommandTermination(cmd, cancelCtx)
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
log.Debug().Msg(color.HiMagentaString("[HOT RELOAD] | Checking for environment updates..."))
|
||||||
|
newEnv, newEtag, err := createInjectableEnvironment(
|
||||||
|
reloadParameters.GetSecretsDetails,
|
||||||
|
reloadParameters.ProjectConfigDir,
|
||||||
|
reloadParameters.SecretOverriding,
|
||||||
|
reloadParameters.ExpandSecrets,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("[HOT RELOAD] | Failed to fetch new secrets")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if newEtag != reloadParameters.InitialETag {
|
||||||
|
log.Info().Msg("[HOT RELOAD] Environment changed. Reloading application...")
|
||||||
|
reloadParameters.InitialETag = newEtag
|
||||||
|
env = newEnv
|
||||||
|
secretsCount = len(newEnv)
|
||||||
|
startCmd() // Restart the command with new environment
|
||||||
|
} else {
|
||||||
|
log.Debug().Msg("Not reloading because environments are identical")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func execCmd(cmd *exec.Cmd) error {
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return fmt.Errorf("failed to start command: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := cmd.Wait(); err != nil {
|
if err := cmd.Wait(); err != nil {
|
||||||
_ = cmd.Process.Signal(os.Kill)
|
return err // Return the raw error for more detailed handling in the caller
|
||||||
return fmt.Errorf("failed to wait for command termination: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waitStatus := cmd.ProcessState.Sys().(syscall.WaitStatus)
|
|
||||||
os.Exit(waitStatus.ExitStatus())
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func execCommandWithReload(cmd *exec.Cmd, cancel context.CancelFunc) {
|
||||||
|
err := execCmd(cmd)
|
||||||
|
if err != nil {
|
||||||
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
if exitErr.ExitCode() == -1 {
|
||||||
|
// This is hit when the command exits due to a reload signal.
|
||||||
|
log.Debug().Msg(color.HiMagentaString("[HOT RELOAD] Process was terminated as part of reload, this is expected behavior"))
|
||||||
|
} else {
|
||||||
|
// This is hit when the command exits with an unexpected exit code.
|
||||||
|
// This should stop the reload logic and exit the CLI.
|
||||||
|
log.Error().Err(err).Msgf("[HOT RELOAD] Command execution failed with exit code: %d", exitErr.ExitCode())
|
||||||
|
|
||||||
|
// ? Question: If the command throws an error, then the infisical CLI should terminate as well, right?
|
||||||
|
cancel()
|
||||||
|
util.PrintErrorAndExit(exitErr.ExitCode(), err, "[HOT RELOAD] Failed to start command")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is hit due to generic errors, not exit errors. This is a catch-all for any other errors.
|
||||||
|
cancel()
|
||||||
|
util.HandleError(err, "[HOT RELOAD] Command execution failed")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the command exits, the CLI should terminate as well
|
||||||
|
log.Debug().Msg(color.HiMagentaString("Command exited without faults"))
|
||||||
|
cancel()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCommandTermination(cmd *exec.Cmd, cmdCancel context.CancelFunc) {
|
||||||
|
|
||||||
|
{
|
||||||
|
if cmd != nil && cmd.Process != nil {
|
||||||
|
log.Info().Msg(color.HiMagentaString("[HOT RELOAD] Terminating existing process..."))
|
||||||
|
if err := cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||||
|
log.Error().Err(err).Msg("[HOT RELOAD] Failed to terminate process")
|
||||||
|
if err := cmd.Process.Kill(); err != nil {
|
||||||
|
log.Error().Err(err).Msg("[HOT RELOAD] Failed to kill process")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cmdCancel != nil {
|
||||||
|
cmdCancel()
|
||||||
|
}
|
||||||
|
// Wait for the process to finish
|
||||||
|
_, err := cmd.Process.Wait()
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() != "wait: no child processes" {
|
||||||
|
log.Error().Err(err).Msg("[HOT RELOAD] Error waiting for process to terminate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createInjectableEnvironment(request models.GetAllSecretsParameters, projectConfigDir string, secretOverriding bool, shouldExpandSecrets bool, token *models.TokenDetails) ([]string, string, error) {
|
||||||
|
|
||||||
|
secrets, err := util.GetAllEnvironmentVariables(request, projectConfigDir)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if secretOverriding {
|
||||||
|
secrets = util.OverrideSecrets(secrets, util.SECRET_TYPE_PERSONAL)
|
||||||
|
} else {
|
||||||
|
secrets = util.OverrideSecrets(secrets, util.SECRET_TYPE_SHARED)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldExpandSecrets {
|
||||||
|
|
||||||
|
authParams := models.ExpandSecretsAuthentication{}
|
||||||
|
|
||||||
|
if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER {
|
||||||
|
authParams.InfisicalToken = token.Token
|
||||||
|
} else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER {
|
||||||
|
authParams.UniversalAuthAccessToken = token.Token
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets = util.ExpandSecrets(secrets, authParams, projectConfigDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
secretsByKey := getSecretsByKeys(secrets)
|
||||||
|
environmentVariables := make(map[string]string)
|
||||||
|
|
||||||
|
// add all existing environment vars
|
||||||
|
for _, s := range os.Environ() {
|
||||||
|
kv := strings.SplitN(s, "=", 2)
|
||||||
|
key := kv[0]
|
||||||
|
value := kv[1]
|
||||||
|
environmentVariables[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if there are any reserved key words in secrets to inject
|
||||||
|
filterReservedEnvVars(secretsByKey)
|
||||||
|
|
||||||
|
// now add infisical secrets
|
||||||
|
for k, v := range secretsByKey {
|
||||||
|
environmentVariables[k] = v.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and sort the env slice using slices.SortFunc
|
||||||
|
env := make([]string, 0, len(environmentVariables))
|
||||||
|
for key, value := range environmentVariables {
|
||||||
|
env = append(env, key+"="+value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, util.GenerateETagFromSecrets(secrets), nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user