fix: preserve named targets in config environment files

Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
Feng Ruohang
2026-08-28 08:57:22 +08:00
parent e73436c99d
commit 2aea7fe9c4
2 changed files with 46 additions and 19 deletions
+4 -7
View File
@@ -37,6 +37,7 @@ import (
"syscall" "syscall"
"time" "time"
"unicode" "unicode"
"unicode/utf8"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
fcolor "github.com/fatih/color" fcolor "github.com/fatih/color"
@@ -542,21 +543,17 @@ func (e envKV) String() string {
} }
func isValidEnvName(name string) bool { func isValidEnvName(name string) bool {
if name == "" || !isEnvNameStart(name[0]) { if name == "" || !utf8.ValidString(name) {
return false return false
} }
for i := 1; i < len(name); i++ { for _, ch := range name {
if !isEnvNameStart(name[i]) && (name[i] < '0' || name[i] > '9') { if ch == '=' || unicode.IsSpace(ch) || !unicode.IsGraphic(ch) {
return false return false
} }
} }
return true return true
} }
func isEnvNameStart(ch byte) bool {
return ch == '_' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z'
}
func trimExportPrefix(envEntry string) string { func trimExportPrefix(envEntry string) string {
rest, ok := strings.CutPrefix(envEntry, "export") rest, ok := strings.CutPrefix(envEntry, "export")
if !ok || rest == "" { if !ok || rest == "" {
+42 -12
View File
@@ -22,8 +22,11 @@ import (
"fmt" "fmt"
"os" "os"
"reflect" "reflect"
"slices"
"strings" "strings"
"testing" "testing"
"github.com/minio/minio/internal/config"
) )
func Test_readFromSecret(t *testing.T) { func Test_readFromSecret(t *testing.T) {
@@ -240,6 +243,19 @@ func Test_minioEnvironFromFileWhitespaceAndValidation(t *testing.T) {
{Key: "_VALID_2", Value: "value"}, {Key: "_VALID_2", Value: "value"},
}, },
}, },
{
name: "named target punctuation and unicode",
content: "MINIO_NOTIFY_WEBHOOK_ENABLE_my-hook=off\n" +
"MINIO_NOTIFY_WEBHOOK_ENABLE_site.eu=off\n" +
"MINIO_NOTIFY_WEBHOOK_ENABLE_team:blue=off\n" +
"MINIO_NOTIFY_WEBHOOK_ENABLE_目标=off",
want: []envKV{
{Key: "MINIO_NOTIFY_WEBHOOK_ENABLE_my-hook", Value: "off"},
{Key: "MINIO_NOTIFY_WEBHOOK_ENABLE_site.eu", Value: "off"},
{Key: "MINIO_NOTIFY_WEBHOOK_ENABLE_team:blue", Value: "off"},
{Key: "MINIO_NOTIFY_WEBHOOK_ENABLE_目标", Value: "off"},
},
},
{ {
name: "missing separator redacts the line", name: "missing separator redacts the line",
content: "MINIO_ROOT_PASSWORD=valid\nsuper-secret-without-equals", content: "MINIO_ROOT_PASSWORD=valid\nsuper-secret-without-equals",
@@ -255,18 +271,12 @@ func Test_minioEnvironFromFileWhitespaceAndValidation(t *testing.T) {
errExcludes: "empty-name-secret", errExcludes: "empty-name-secret",
}, },
{ {
name: "digit leading name", name: "os compatible leading digit and punctuation",
content: "1MINIO_ROOT_USER=digit-leading-secret", content: "1MINIO_ROOT_USER=digit-leading-secret\n-MINIO-ROOT-USER=hyphen-secret",
errLine: 1, want: []envKV{
errContains: `invalid environment variable name "1MINIO_ROOT_USER"`, {Key: "1MINIO_ROOT_USER", Value: "digit-leading-secret"},
errExcludes: "digit-leading-secret", {Key: "-MINIO-ROOT-USER", Value: "hyphen-secret"},
}, },
{
name: "hyphenated name",
content: "MINIO-ROOT-USER=hyphen-secret",
errLine: 1,
errContains: `invalid environment variable name "MINIO-ROOT-USER"`,
errExcludes: "hyphen-secret",
}, },
{ {
name: "whitespace in name", name: "whitespace in name",
@@ -282,6 +292,13 @@ func Test_minioEnvironFromFileWhitespaceAndValidation(t *testing.T) {
errContains: "invalid environment variable name", errContains: "invalid environment variable name",
errExcludes: "nul-name-secret", errExcludes: "nul-name-secret",
}, },
{
name: "format character in name",
content: "MINIO\u200bROOT=format-secret",
errLine: 1,
errContains: "invalid environment variable name",
errExcludes: "format-secret",
},
{ {
name: "NUL in value", name: "NUL in value",
content: "MINIO_ROOT_USER=before\x00nul-value-secret", content: "MINIO_ROOT_USER=before\x00nul-value-secret",
@@ -342,3 +359,16 @@ func Test_minioEnvironFromFileWhitespaceAndValidation(t *testing.T) {
}) })
} }
} }
func TestConfigEnvFileNamedTargetDiscovery(t *testing.T) {
key := "MINIO_NOTIFY_WEBHOOK_ENABLE_my-hook"
t.Setenv(key, "off")
targets, err := (config.Config{}).GetAvailableTargets(config.NotifyWebhookSubSys)
if err != nil {
t.Fatal(err)
}
if !slices.Contains(targets, "my-hook") {
t.Fatalf("named target %q not discovered from %s: %v", "my-hook", key, targets)
}
}