Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 51 additions & 25 deletions cmd/satellite/main.go
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"log"
"os"
"strings"
"time"

"github.com/container-registry/harbor-satellite/internal/env"
Expand Down Expand Up @@ -59,7 +60,6 @@ type SatelliteOptions struct {
DirectDelivery bool
ImageDir string
}

func main() {
_ = godotenv.Load(".env") //nolint:errcheck // .env file is optional

Expand Down Expand Up @@ -108,11 +108,11 @@ func main() {
flag.StringVar(&opts.ImageDir, "image-dir", opts.ImageDir, "Override image directory for direct delivery (auto-detected if empty)")

flag.Parse()
if opts.Token == "" {
opts.Token = envCfg.Token

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When users provide TOKEN without --token, startup now leaves opts.Token empty and fails required-token validation; REGISTRY_PASSWORD is likewise lost for BYO registry authentication. Restore the post-parse environment fallback, using strings.TrimSpace to preserve CLI-over-environment precedence for whitespace-only values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At cmd/satellite/main.go, line 112:

<comment>When users provide `TOKEN` without `--token`, startup now leaves `opts.Token` empty and fails required-token validation; `REGISTRY_PASSWORD` is likewise lost for BYO registry authentication. Restore the post-parse environment fallback, using `strings.TrimSpace` to preserve CLI-over-environment precedence for whitespace-only values.</comment>

<file context>
@@ -108,13 +108,6 @@ func main() {
-		opts.RegistryPassword = envCfg.RegistryPassword
-	}
 
 	// Validate and trim options
 	if err := validateAndTrimOptions(&opts, &shutdownTimeout); err != nil {
</file context>

}
if opts.RegistryPassword == "" {
opts.RegistryPassword = envCfg.RegistryPassword

// Validate and trim options
if err := validateAndTrimOptions(&opts, &shutdownTimeout); err != nil {
fmt.Printf("Invalid arguments: %v\n", err)
os.Exit(1)
}

// Resolve config directory path
Expand All @@ -136,34 +136,60 @@ func main() {
pathConfig.ZotStorageDir = opts.RegistryDataDir
}

err = run(opts, pathConfig, shutdownTimeout)
if err != nil {
fmt.Printf("fatal: %v\n", err)
os.Exit(1)
}
}
func validateAndTrimOptions(opts *SatelliteOptions, shutdownTimeout *string) error {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
// Trim string fields where leading/trailing whitespace is meaningless
// NOTE: We do NOT trim RegistryPassword as it may contain intentional whitespace
// NOTE: We do NOT trim filesystem paths (ConfigDir, RegistryDataDir, ImageDir, SPIFFEEndpointSocket)
// as they may contain intentional leading/trailing spaces in some edge cases
opts.GroundControlURL = strings.TrimSpace(opts.GroundControlURL)
opts.Token = strings.TrimSpace(opts.Token)
opts.HarborRegistryURL = strings.TrimSpace(opts.HarborRegistryURL)
opts.RegistryURL = strings.TrimSpace(opts.RegistryURL)
opts.RegistryUsername = strings.TrimSpace(opts.RegistryUsername)
// NOTE: Intentionally NOT trimming RegistryPassword
opts.ConfigDir = strings.TrimSpace(opts.ConfigDir)
opts.RegistryDataDir = strings.TrimSpace(opts.RegistryDataDir)
opts.ImageDir = strings.TrimSpace(opts.ImageDir)
opts.SPIFFEEndpointSocket = strings.TrimSpace(opts.SPIFFEEndpointSocket)
opts.SPIFFEExpectedServerID = strings.TrimSpace(opts.SPIFFEExpectedServerID)
*shutdownTimeout = strings.TrimSpace(*shutdownTimeout)

// For --fallback-only mode, relax token/gc-url requirements
if !opts.FallbackOnly {
if !opts.SPIFFEEnabled && (opts.Token == "" || opts.GroundControlURL == "") {
fmt.Println("Missing required arguments: --token and --ground-control-url or matching env vars (or enable SPIFFE with --spiffe-enabled).")
os.Exit(1)
}
if opts.GroundControlURL == "" {
fmt.Println("Missing required argument: --ground-control-url or GROUND_CONTROL_URL env var.")
os.Exit(1)
}
if opts.HarborRegistryURL == "" {
fmt.Println("Missing required argument: --harbor-registry-url or HARBOR_REGISTRY_URL env var.")
os.Exit(1)
if !opts.SPIFFEEnabled {
// In non-SPIFFE mode, token and ground-control-url are required
if opts.Token == "" {
return fmt.Errorf("missing required argument: --token or matching env vars (or enable SPIFFE with --spiffe-enabled)")
}
if opts.GroundControlURL == "" {
return fmt.Errorf("missing required argument: --ground-control-url or GROUND_CONTROL_URL env var")
}
if opts.HarborRegistryURL == "" {
return fmt.Errorf("missing required argument: --harbor-registry-url or HARBOR_REGISTRY_URL env var")
}
} else {
// In SPIFFE mode, we only need harbor-registry-url
if opts.HarborRegistryURL == "" {
return fmt.Errorf("missing required argument: --harbor-registry-url or HARBOR_REGISTRY_URL env var")
}
}
}
if opts.GroundControlURL == "" {
// Set default GroundControlURL if empty and not in SPIFFE mode
// (after validation so we don't override explicit empty)
if opts.GroundControlURL == "" && !opts.SPIFFEEnabled {
opts.GroundControlURL = config.DefaultGroundControlURL
}
if opts.BYORegistry && opts.RegistryURL == "" {
fmt.Println("Missing required argument: --registry-url is required when --byo-registry is enabled.")
os.Exit(1)
return fmt.Errorf("missing required argument: --registry-url is required when --byo-registry is enabled")
}

err = run(opts, pathConfig, shutdownTimeout)
if err != nil {
fmt.Printf("fatal: %v\n", err)
os.Exit(1)
}
return nil
}

// reconfigureAuditOnReload swaps the audit logger to match next when the audit
Expand Down
Loading