Sanitize duplicate allowed_nodes blocks
This commit is contained in:
parent
2e7f693c8b
commit
936894a5fe
2 changed files with 100 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -85,6 +86,10 @@ func loadConfig(configPath string) (*Config, error) {
|
||||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sanitized, newData := sanitizeDuplicateAllowedNodesBlocks(configPath, data); sanitized {
|
||||||
|
data = newData
|
||||||
|
}
|
||||||
|
|
||||||
if err := yaml.Unmarshal(data, cfg); err != nil {
|
if err := yaml.Unmarshal(data, cfg); err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -518,6 +523,49 @@ func detectHostCIDRs() []string {
|
||||||
return cidrs
|
return cidrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var allowedNodesBlockPattern = regexp.MustCompile(`(?m)(?:^[ \t]*#.*\n)*^[ \t]*allowed_nodes:\n(?:^[ \t]+-.*\n?)+`)
|
||||||
|
|
||||||
|
func sanitizeDuplicateAllowedNodesBlocks(path string, data []byte) (bool, []byte) {
|
||||||
|
matches := allowedNodesBlockPattern.FindAllIndex(data, -1)
|
||||||
|
if len(matches) <= 1 {
|
||||||
|
return false, data
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
last := 0
|
||||||
|
for idx, match := range matches {
|
||||||
|
start, end := match[0], match[1]
|
||||||
|
if idx == 0 {
|
||||||
|
buf.Write(data[last:end])
|
||||||
|
} else {
|
||||||
|
buf.Write(data[last:start])
|
||||||
|
}
|
||||||
|
last = end
|
||||||
|
}
|
||||||
|
buf.Write(data[last:])
|
||||||
|
|
||||||
|
cleaned := buf.Bytes()
|
||||||
|
if path != "" {
|
||||||
|
if err := os.WriteFile(path, cleaned, 0600); err != nil {
|
||||||
|
log.Warn().
|
||||||
|
Err(err).
|
||||||
|
Str("config_file", path).
|
||||||
|
Msg("Failed to rewrite sanitized configuration; using in-memory copy only")
|
||||||
|
} else {
|
||||||
|
log.Warn().
|
||||||
|
Str("config_file", path).
|
||||||
|
Int("removed_duplicate_blocks", len(matches)-1).
|
||||||
|
Msg("Detected duplicate allowed_nodes blocks and sanitized configuration automatically")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn().
|
||||||
|
Int("removed_duplicate_blocks", len(matches)-1).
|
||||||
|
Msg("Detected duplicate allowed_nodes blocks and sanitized configuration (in-memory only)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, cleaned
|
||||||
|
}
|
||||||
|
|
||||||
// parseAllowedSubnets validates and normalizes subnet specifications
|
// parseAllowedSubnets validates and normalizes subnet specifications
|
||||||
func parseAllowedSubnets(cfg []string) ([]string, error) {
|
func parseAllowedSubnets(cfg []string) ([]string, error) {
|
||||||
seen := make(map[string]struct{})
|
seen := make(map[string]struct{})
|
||||||
|
|
|
||||||
52
cmd/pulse-sensor-proxy/config_test.go
Normal file
52
cmd/pulse-sensor-proxy/config_test.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSanitizeDuplicateAllowedNodesBlocks_RemovesExtraBlocks(t *testing.T) {
|
||||||
|
raw := `
|
||||||
|
allowed_nodes:
|
||||||
|
- delly
|
||||||
|
- minipc
|
||||||
|
|
||||||
|
# Cluster nodes (auto-discovered during installation)
|
||||||
|
# These nodes are allowed to request temperature data when cluster IPC validation is unavailable
|
||||||
|
allowed_nodes:
|
||||||
|
- delly
|
||||||
|
- minipc
|
||||||
|
- extra
|
||||||
|
`
|
||||||
|
|
||||||
|
sanitized, out := sanitizeDuplicateAllowedNodesBlocks("", []byte(raw))
|
||||||
|
if !sanitized {
|
||||||
|
t.Fatalf("expected sanitization to occur")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := string(out)
|
||||||
|
if strings.Count(result, "allowed_nodes:") != 1 {
|
||||||
|
t.Fatalf("expected only one allowed_nodes block, got %q", result)
|
||||||
|
}
|
||||||
|
if strings.Contains(result, "extra") {
|
||||||
|
t.Fatalf("duplicate entries should be removed, got %q", result)
|
||||||
|
}
|
||||||
|
if strings.Contains(result, "Cluster nodes (auto-discovered during installation)") {
|
||||||
|
t.Fatalf("duplicate comment block should be removed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSanitizeDuplicateAllowedNodesBlocks_NoChangeWhenUnique(t *testing.T) {
|
||||||
|
raw := `
|
||||||
|
metrics_address: 127.0.0.1:9127
|
||||||
|
allowed_nodes:
|
||||||
|
- delly
|
||||||
|
`
|
||||||
|
sanitized, out := sanitizeDuplicateAllowedNodesBlocks("", []byte(raw))
|
||||||
|
if sanitized {
|
||||||
|
t.Fatalf("unexpected sanitization for unique config")
|
||||||
|
}
|
||||||
|
if string(out) != raw {
|
||||||
|
t.Fatalf("expected config to remain unchanged")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue