Skip to content

Commit

Permalink
Allow doppler secrets substitute to use environment vars
Browse files Browse the repository at this point in the history
  • Loading branch information
nmanoogian committed Nov 20, 2024
1 parent a79f327 commit a564422
Showing 1 changed file with 28 additions and 15 deletions.
43 changes: 28 additions & 15 deletions pkg/cmd/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,11 @@ func downloadSecrets(cmd *cobra.Command, args []string) {
func substituteSecrets(cmd *cobra.Command, args []string) {
localConfig := configuration.LocalConfig(cmd)

utils.RequireValue("token", localConfig.Token.Value)
useEnv := cmd.Flag("use-env").Value.String()

if useEnv != "only" {
utils.RequireValue("token", localConfig.Token.Value)
}

var outputFilePath string
var err error
Expand All @@ -586,24 +590,32 @@ func substituteSecrets(cmd *cobra.Command, args []string) {
utils.HandleError(err, "Unable to parse output file path")
}
}
secretsMap := map[string]string{}

dynamicSecretsTTL := utils.GetDurationFlag(cmd, "dynamic-ttl")
response, responseErr := http.GetSecrets(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, localConfig.EnclaveConfig.Value, nil, true, dynamicSecretsTTL)
if !responseErr.IsNil() {
utils.HandleError(responseErr.Unwrap(), responseErr.Message)
if useEnv != "none" {
for k, v := range utils.ParseEnvStrings(os.Environ()) {
secretsMap[k] = v
}
}

secrets, parseErr := models.ParseSecrets(response)
if parseErr != nil {
utils.HandleError(parseErr, "Unable to parse API response")
}
if useEnv != "only" {
dynamicSecretsTTL := utils.GetDurationFlag(cmd, "dynamic-ttl")
response, responseErr := http.GetSecrets(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, localConfig.EnclaveConfig.Value, nil, true, dynamicSecretsTTL)
if !responseErr.IsNil() {
utils.HandleError(responseErr.Unwrap(), responseErr.Message)
}

secretsMap := map[string]string{}
for _, secret := range secrets {
if secret.ComputedValue != nil {
// By not providing a default value when ComputedValue is nil (e.g. it's a restricted secret), we default
// to the same behavior the substituter provides if the template file contains a secret that doesn't exist.
secretsMap[secret.Name] = *secret.ComputedValue
secrets, parseErr := models.ParseSecrets(response)
if parseErr != nil {
utils.HandleError(parseErr, "Unable to parse API response")
}

for _, secret := range secrets {
if secret.ComputedValue != nil {
// By not providing a default value when ComputedValue is nil (e.g. it's a restricted secret), we default
// to the same behavior the substituter provides if the template file contains a secret that doesn't exist.
secretsMap[secret.Name] = *secret.ComputedValue
}
}
}

Expand Down Expand Up @@ -739,6 +751,7 @@ func init() {
if err := secretsSubstituteCmd.RegisterFlagCompletionFunc("config", configNamesValidArgs); err != nil {
utils.HandleError(err)
}
secretsSubstituteCmd.Flags().String("use-env", "none", "setting for how to use environment variables passed to 'doppler secrets substitute'. 'none' (default) will not expose environment variables to templates. 'mix' will expose both templates and Doppler secrets to templates. 'only' will only expose environment variables to templates (and will not fetch Doppler secrets).")
secretsSubstituteCmd.Flags().String("output", "", "path to the output file. by default the rendered text will be written to stdout.")
secretsSubstituteCmd.Flags().Duration("dynamic-ttl", 0, "(BETA) dynamic secrets will expire after specified duration, (e.g. '3h', '15m')")
secretsCmd.AddCommand(secretsSubstituteCmd)
Expand Down

0 comments on commit a564422

Please sign in to comment.