Files
wild-central/internal/api/v1/validation.go
Paul Payne beb643f76f feat: Extract Wild Central as standalone Go service
Extract the Central networking functionality from wild-cloud/api into
a standalone service. Wild Central manages DNS (dnsmasq), gateway
(HAProxy), firewall (nftables), VPN (WireGuard), TLS (certbot),
security (CrowdSec), and DDNS — all the network appliance concerns.

All Cloud-specific code (instances, clusters, nodes, apps, backups,
operations, kubectl/talosctl tooling) has been removed. The API struct
and route registration contain only Central endpoints. Tests updated
to match the new API signature.

Builds and all tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-08 23:31:16 +00:00

81 lines
2.6 KiB
Go

package v1
import (
"fmt"
"regexp"
"strings"
)
const (
maxInstanceNameLength = 63 // Kubernetes DNS label limit (RFC 1123)
maxNodeIdentifierLength = 253 // RFC 1035 hostname limit
)
// validNamePattern matches valid resource names.
// Names must:
// - Start and end with a lowercase letter or number
// - Contain only lowercase letters, numbers, and hyphens
// - Be between 1 and 63 characters
// This follows Kubernetes naming conventions for consistency.
var validNamePattern = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]*[a-z0-9])?$`)
// ValidateName validates a resource name (instance, app, node, etc.).
// Returns an error if the name is invalid.
func ValidateName(name string) error {
if name == "" {
return fmt.Errorf("name is required")
}
if len(name) > maxInstanceNameLength {
return fmt.Errorf("name must be %d characters or less", maxInstanceNameLength)
}
if !validNamePattern.MatchString(name) {
return fmt.Errorf("name must contain only lowercase letters, numbers, and hyphens, and must start and end with a letter or number")
}
return nil
}
// ValidateInstanceName validates an instance name with a user-friendly error message.
func ValidateInstanceName(name string) error {
if err := ValidateName(name); err != nil {
return fmt.Errorf("invalid instance name: %w", err)
}
return nil
}
// ValidateAppName validates an app name with a user-friendly error message.
func ValidateAppName(name string) error {
if err := ValidateName(name); err != nil {
return fmt.Errorf("invalid app name: %w", err)
}
return nil
}
// ValidateServiceName validates a service name with a user-friendly error message.
func ValidateServiceName(name string) error {
if err := ValidateName(name); err != nil {
return fmt.Errorf("invalid service name: %w", err)
}
return nil
}
// ValidateNodeIdentifier validates a node identifier (hostname or IP).
// Node identifiers have slightly relaxed rules since they can be IPs.
func ValidateNodeIdentifier(identifier string) error {
if identifier == "" {
return fmt.Errorf("node identifier is required")
}
if len(identifier) > maxNodeIdentifierLength {
return fmt.Errorf("node identifier must be %d characters or less", maxNodeIdentifierLength)
}
// Basic check for path traversal
if containsPathTraversal(identifier) {
return fmt.Errorf("invalid node identifier: contains invalid characters")
}
return nil
}
// containsPathTraversal checks if a string contains path traversal patterns.
func containsPathTraversal(s string) bool {
return strings.ContainsAny(s, "/\\") || strings.Contains(s, "..") || strings.ContainsRune(s, '\x00')
}