mirror of
https://github.com/pgsty/minio.git
synced 2026-08-10 00:03:29 +03:00
162ded3438
GetNotifyNATS reads user_credentials, nkey_seed and tls_handshake_first and GetNotifyAMQP reads immediate, but none of them were registered in DefaultNATSKVS/DefaultAMQPKVS or the help schema, so CheckValidKeys rejected any enable=on target carrying them. Worse, the legacy config migration wrote exactly these keys - including the env var name MINIO_NOTIFY_NATS_USER_CREDENTIALS used as a config key, because the NATSUserCredentials constant doubled as both - so a migrated NATS config failed validation on every load, and the FetchEnabledTargets fail-fast then silently disabled all bucket notification targets. - Register user_credentials/nkey_seed/tls_handshake_first (NATS) and immediate (AMQP) in the default KVS and help schema; split NATSUserCredentials into a real config key plus EnvNATSUserCredentials (all env var names byte-stable) - Fix legacy migration: SetNotifyNATS writes the proper key; SetNotifyAMQP no longer writes cfg.Immediate under the internal key and now carries both immediate and internal - Tolerate the legacy MINIO_NOTIFY_NATS_USER_CREDENTIALS key written by pre-fix migrations (NATS-scoped, load path only) with fallback read; env > user_credentials > legacy key - Print key names only, never values, in the invalid-keys error of both CheckValidKeys forms; rejected values can carry credentials - Add an AST-based audit test asserting parser reads, migration writes and help entries stay within the registered key set for all ten notify subsystems, with floor assertions so collector drift fails loudly - Document (unchanged) FetchEnabledTargets fail-fast and pin it with a characterization test Known same-class gap left in place and pinned by the audit's allowlist: SetNotifyPostgres/SetNotifyMySQL write five unregistered DSN-era keys; tracked for a follow-up issue. Closes #39 Co-authored-by: ChatGPT <noreply@openai.com> Co-authored-by: Claude <noreply@anthropic.com>
116 lines
3.7 KiB
Go
116 lines
3.7 KiB
Go
// Copyright (c) 2015-2026 MinIO, Inc.
|
|
//
|
|
// This file is part of MinIO Object Storage stack
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package notify
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/minio/minio/internal/config"
|
|
"github.com/minio/minio/internal/event/target"
|
|
xnet "github.com/minio/pkg/v3/net"
|
|
"github.com/rabbitmq/amqp091-go"
|
|
)
|
|
|
|
// T5 (NATS): a config produced by the legacy migration must survive validation
|
|
// and round-trip back through the parser unchanged. Before the fix the
|
|
// migration wrote an env var name as a config key, so every migrated NATS
|
|
// target failed CheckValidKeys on the next config load.
|
|
func TestSetNotifyNATSRoundTrip(t *testing.T) {
|
|
addr, err := xnet.ParseHost(testNATSAddr)
|
|
if err != nil {
|
|
t.Fatalf("ParseHost: %v", err)
|
|
}
|
|
|
|
args := target.NATSArgs{
|
|
Enable: true,
|
|
Address: *addr,
|
|
Subject: testNATSSubj,
|
|
UserCredentials: testCredsPath,
|
|
NKeySeed: testNKeyPath,
|
|
TLSHandshakeFirst: true,
|
|
}
|
|
|
|
s := config.Config{config.NotifyNATSSubSys: map[string]config.KVS{}}
|
|
if err := SetNotifyNATS(s, testTargetName, args); err != nil {
|
|
t.Fatalf("SetNotifyNATS: %v", err)
|
|
}
|
|
|
|
if err := checkValidNotificationKeysForSubSys(config.NotifyNATSSubSys, s[config.NotifyNATSSubSys]); err != nil {
|
|
t.Fatalf("migrated NATS config must pass key validation, got: %v", err)
|
|
}
|
|
|
|
targets, err := GetNotifyNATS(s[config.NotifyNATSSubSys], nil)
|
|
if err != nil {
|
|
t.Fatalf("GetNotifyNATS: %v", err)
|
|
}
|
|
got, ok := targets[testTargetName]
|
|
if !ok {
|
|
t.Fatalf("target %q missing after round trip: %v", testTargetName, targets)
|
|
}
|
|
if got.UserCredentials != args.UserCredentials {
|
|
t.Errorf("UserCredentials = %q, want %q", got.UserCredentials, args.UserCredentials)
|
|
}
|
|
if got.NKeySeed != args.NKeySeed {
|
|
t.Errorf("NKeySeed = %q, want %q", got.NKeySeed, args.NKeySeed)
|
|
}
|
|
if got.TLSHandshakeFirst != args.TLSHandshakeFirst {
|
|
t.Errorf("TLSHandshakeFirst = %v, want %v", got.TLSHandshakeFirst, args.TLSHandshakeFirst)
|
|
}
|
|
}
|
|
|
|
// T5 (AMQP): the migration mapped cfg.Immediate onto the `internal` key and
|
|
// dropped cfg.Internal entirely, so a migrated target came back with both
|
|
// fields wrong.
|
|
func TestSetNotifyAMQPRoundTrip(t *testing.T) {
|
|
uri, err := amqp091.ParseURI(testAMQPURL)
|
|
if err != nil {
|
|
t.Fatalf("ParseURI: %v", err)
|
|
}
|
|
|
|
args := target.AMQPArgs{
|
|
Enable: true,
|
|
URL: uri,
|
|
Immediate: true,
|
|
Internal: false,
|
|
}
|
|
|
|
s := config.Config{config.NotifyAMQPSubSys: map[string]config.KVS{}}
|
|
if err := SetNotifyAMQP(s, testTargetName, args); err != nil {
|
|
t.Fatalf("SetNotifyAMQP: %v", err)
|
|
}
|
|
|
|
if err := checkValidNotificationKeysForSubSys(config.NotifyAMQPSubSys, s[config.NotifyAMQPSubSys]); err != nil {
|
|
t.Fatalf("migrated AMQP config must pass key validation, got: %v", err)
|
|
}
|
|
|
|
targets, err := GetNotifyAMQP(s[config.NotifyAMQPSubSys])
|
|
if err != nil {
|
|
t.Fatalf("GetNotifyAMQP: %v", err)
|
|
}
|
|
got, ok := targets[testTargetName]
|
|
if !ok {
|
|
t.Fatalf("target %q missing after round trip: %v", testTargetName, targets)
|
|
}
|
|
if !got.Immediate {
|
|
t.Errorf("Immediate = false, want true")
|
|
}
|
|
if got.Internal {
|
|
t.Errorf("Internal = true, want false (immediate must not be written to the internal key)")
|
|
}
|
|
}
|