feat(installer): activate source builds atomically
Все проверки выполнены успешно
CI / test (push) Successful in 4m30s
Docker / Build and publish worker image (push) Successful in 17m26s
Все проверки выполнены успешно
CI / test (push) Successful in 4m30s
Docker / Build and publish worker image (push) Successful in 17m26s
Этот коммит содержится в:
@@ -478,6 +478,16 @@ func ValidateEnvironmentFile(path string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("read worker environment: %w", err)
|
||||
}
|
||||
_, err = parseEnvironmentContent(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// parseEnvironmentContent validates systemd-safe KEY=VALUE environment
|
||||
// content and returns the parsed map. Values must not use quoting,
|
||||
// interpolation, or whitespace; RSMON_URL and RSMON_TOKEN are required and
|
||||
// must not be duplicated. Operating on the already-read bytes (rather
|
||||
// than a path) keeps callers free of read-to-validate TOCTOU races.
|
||||
func parseEnvironmentContent(data []byte) (map[string]string, error) {
|
||||
values := make(map[string]string)
|
||||
seenRequired := make(map[string]bool)
|
||||
for number, line := range strings.Split(string(data), "\n") {
|
||||
@@ -486,30 +496,30 @@ func ValidateEnvironmentFile(path string) error {
|
||||
continue
|
||||
}
|
||||
if strings.ContainsRune(line, '\r') {
|
||||
return fmt.Errorf("worker environment line %d contains a carriage return", lineNumber)
|
||||
return nil, fmt.Errorf("worker environment line %d contains a carriage return", lineNumber)
|
||||
}
|
||||
key, value, ok := strings.Cut(line, "=")
|
||||
if !ok || !envKeyPattern.MatchString(key) {
|
||||
return fmt.Errorf("worker environment line %d must use KEY=VALUE syntax", lineNumber)
|
||||
return nil, fmt.Errorf("worker environment line %d must use KEY=VALUE syntax", lineNumber)
|
||||
}
|
||||
if err := validateEnvValue(key, value); err != nil {
|
||||
return fmt.Errorf("worker environment line %d: %w", lineNumber, err)
|
||||
return nil, fmt.Errorf("worker environment line %d: %w", lineNumber, err)
|
||||
}
|
||||
if key == "RSMON_URL" || key == "RSMON_TOKEN" {
|
||||
if seenRequired[key] {
|
||||
return fmt.Errorf("worker environment line %d duplicates %s", lineNumber, key)
|
||||
return nil, fmt.Errorf("worker environment line %d duplicates %s", lineNumber, key)
|
||||
}
|
||||
seenRequired[key] = true
|
||||
}
|
||||
values[key] = value
|
||||
}
|
||||
if err := ValidateURL(values["RSMON_URL"]); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if err := ValidateToken(values["RSMON_TOKEN"]); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// validateEnvValue enforces the value rules shared by the strict env
|
||||
|
||||
Ссылка в новой задаче
Block a user