mirror of
https://github.com/helmfile/helmfile.git
synced 2026-09-30 22:47:04 +02:00
* fix: error on missing secret key when using vals Add HELMFILE_VALS_FAIL_ON_MISSING_KEY_IN_MAP environment variable to control whether vals should fail when a referenced key does not exist in the secret map. Previously, when a secret reference like ref+vault://path#/nonexistent-key pointed to a non-existent key, vals would silently return an empty string without error. This could lead to deployments with missing configuration. Default behavior remains backward compatible (returns empty string). Set HELMFILE_VALS_FAIL_ON_MISSING_KEY_IN_MAP=true to enable strict mode. Fixes #1563 Signed-off-by: yxxhero <aiopsclub@163.com> * refactor: extract buildValsOptions helper and improve tests - Extract buildValsOptions() to make vals configuration testable - Use t.Setenv instead of manual env save/restore in tests - Test actual vals.Options output including FailOnMissingKeyInMap Addresses PR review comments on #2496 Signed-off-by: yxxhero <aiopsclub@163.com> * fix: use strconv.ParseBool and make tests hermetic - Use strconv.ParseBool for FailOnMissingKeyInMap parsing to support common boolean values like 'TRUE', '1', '0', etc. - Always set env vars explicitly in tests (even to empty string) to prevent flaky tests when env vars are set externally - Add test cases for various boolean formats Signed-off-by: yxxhero <aiopsclub@163.com> * docs: add documentation for vals-related environment variables Add documentation for: - HELMFILE_AWS_SDK_LOG_LEVEL: configure AWS SDK logging for vals - HELMFILE_VALS_FAIL_ON_MISSING_KEY_IN_MAP: enable strict mode for secret refs Signed-off-by: yxxhero <aiopsclub@163.com> * fix: improve error handling and case-insensitive comparison - buildValsOptions now returns error for invalid boolean values instead of silently defaulting to false - Use strings.EqualFold for case-insensitive 'off' comparison to handle OFF, Off, etc. - Add test cases for invalid boolean and uppercase OFF - Update docs to mention case-insensitive and error behavior Signed-off-by: yxxhero <aiopsclub@163.com> * fix: normalize log level and improve singleton initialization - Normalize AWS log level 'off' to lowercase for true case-insensitivity - Replace sync.Once with mutex to allow recovery from config errors - Update tests to expect normalized 'off' value - Update docs to clarify when error is raised Signed-off-by: yxxhero <aiopsclub@163.com> --------- Signed-off-by: yxxhero <aiopsclub@163.com>
101 lines
2.7 KiB
Go
101 lines
2.7 KiB
Go
package plugins
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/helmfile/vals"
|
|
|
|
"github.com/helmfile/helmfile/pkg/envvar"
|
|
)
|
|
|
|
const (
|
|
// cache size for improving performance of ref+.* secrets rendering
|
|
valsCacheSize = 512
|
|
)
|
|
|
|
var instance *vals.Runtime
|
|
var mu sync.Mutex
|
|
|
|
func buildValsOptions() (vals.Options, error) {
|
|
// Configure AWS SDK logging via HELMFILE_AWS_SDK_LOG_LEVEL environment variable
|
|
// Default: "off" to prevent sensitive information (tokens, auth headers) from being exposed
|
|
// See issue #2270 and vals PR helmfile/vals#893
|
|
//
|
|
// Valid values:
|
|
// - "off" (default): No AWS SDK logging - secure, prevents credential leakage
|
|
// - "minimal": Log retries only - minimal debugging info
|
|
// - "standard": Log retries + requests - moderate debugging (previous default)
|
|
// - "verbose": Log everything - full debugging (requests, responses, bodies, signing)
|
|
// - Custom: Comma-separated values like "request,response"
|
|
//
|
|
// Note: AWS_SDK_GO_LOG_LEVEL environment variable always takes precedence over this setting
|
|
// Note: Case-insensitive for known values like "off", "OFF", "Off"
|
|
logLevel := strings.TrimSpace(os.Getenv(envvar.AWSSDKLogLevel))
|
|
|
|
// Configure fail on missing key behavior
|
|
// Default to false for backward compatibility
|
|
// Set HELMFILE_VALS_FAIL_ON_MISSING_KEY_IN_MAP=true to enable strict mode
|
|
// Supports common boolean values: "true", "TRUE", "1", etc.
|
|
// See issue #1563
|
|
envVal := strings.TrimSpace(os.Getenv(envvar.ValsFailOnMissingKeyInMap))
|
|
var failOnMissingKey bool
|
|
if envVal != "" {
|
|
var err error
|
|
failOnMissingKey, err = strconv.ParseBool(envVal)
|
|
if err != nil {
|
|
return vals.Options{}, fmt.Errorf("invalid value for %s: %q (must be a valid boolean)", envvar.ValsFailOnMissingKeyInMap, envVal)
|
|
}
|
|
}
|
|
|
|
// Default to "off" for security if not specified
|
|
if logLevel == "" {
|
|
logLevel = "off"
|
|
}
|
|
|
|
// Normalize known values to lowercase for case-insensitive handling
|
|
if strings.EqualFold(logLevel, "off") {
|
|
logLevel = "off"
|
|
}
|
|
|
|
opts := vals.Options{
|
|
CacheSize: valsCacheSize,
|
|
FailOnMissingKeyInMap: failOnMissingKey,
|
|
AWSLogLevel: logLevel,
|
|
}
|
|
|
|
// Also suppress vals' own internal logging unless user wants verbose output
|
|
// This prevents vals' log messages (separate from AWS SDK logs) from exposing credentials
|
|
if logLevel == "off" {
|
|
opts.LogOutput = io.Discard
|
|
}
|
|
// For other levels, allow vals to log to default output for debugging
|
|
|
|
return opts, nil
|
|
}
|
|
|
|
func ValsInstance() (*vals.Runtime, error) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
if instance != nil {
|
|
return instance, nil
|
|
}
|
|
|
|
opts, err := buildValsOptions()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
instance, err = vals.New(opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return instance, nil
|
|
}
|