feat: add builder mode for centralized Nix builds #2
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -13,6 +14,10 @@ import (
|
|||||||
"git.t-juice.club/torjus/homelab-deploy/internal/nats"
|
"git.t-juice.club/torjus/homelab-deploy/internal/nats"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// hostnameRegex validates hostnames from flake output.
|
||||||
|
// Allows: alphanumeric, dashes, underscores, dots.
|
||||||
|
var hostnameRegex = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`)
|
||||||
|
|
||||||
// BuilderConfig holds the configuration for the builder.
|
// BuilderConfig holds the configuration for the builder.
|
||||||
type BuilderConfig struct {
|
type BuilderConfig struct {
|
||||||
NATSUrl string
|
NATSUrl string
|
||||||
@@ -197,6 +202,16 @@ func (b *Builder) handleBuildRequest(subject string, data []byte) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Filter out hostnames with invalid characters (security: prevent injection)
|
||||||
|
validHosts := make([]string, 0, len(hosts))
|
||||||
|
for _, host := range hosts {
|
||||||
|
if hostnameRegex.MatchString(host) {
|
||||||
|
validHosts = append(validHosts, host)
|
||||||
|
} else {
|
||||||
|
b.logger.Warn("skipping hostname with invalid characters", "hostname", host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hosts = validHosts
|
||||||
// Sort hosts for consistent ordering
|
// Sort hosts for consistent ordering
|
||||||
sort.Strings(hosts)
|
sort.Strings(hosts)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ func (r *BuildRequest) Validate() error {
|
|||||||
if r.Target == "" {
|
if r.Target == "" {
|
||||||
return fmt.Errorf("target is required")
|
return fmt.Errorf("target is required")
|
||||||
}
|
}
|
||||||
|
// Target must be "all" or a valid hostname (same format as revision/branch)
|
||||||
|
if r.Target != "all" && !revisionRegex.MatchString(r.Target) {
|
||||||
|
return fmt.Errorf("invalid target format: %q", r.Target)
|
||||||
|
}
|
||||||
if r.Branch != "" && !revisionRegex.MatchString(r.Branch) {
|
if r.Branch != "" && !revisionRegex.MatchString(r.Branch) {
|
||||||
return fmt.Errorf("invalid branch format: %q", r.Branch)
|
return fmt.Errorf("invalid branch format: %q", r.Branch)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user