feat: add builder mode for centralized Nix builds #2

Merged
torjus merged 4 commits from feat/builder into master 2026-02-10 21:16:05 +00:00
2 changed files with 19 additions and 0 deletions
Showing only changes of commit 08f1fcc6ac - Show all commits

View File

@@ -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 {

View File

@@ -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)
} }