mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
fix: restrict supervisor drain to loopback
This commit is contained in:
@@ -7,7 +7,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
@@ -63,9 +65,32 @@ func New(config Config) (*Supervisor, error) {
|
||||
if config.HTTPClient == nil {
|
||||
config.HTTPClient = http.DefaultClient
|
||||
}
|
||||
if (config.DrainURL == "") != (config.DrainToken == "") {
|
||||
return nil, fmt.Errorf("drain URL and token must be configured together")
|
||||
}
|
||||
if config.DrainURL != "" {
|
||||
if err := validateLocalDrainURL(config.DrainURL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Supervisor{config: config, client: config.HTTPClient}, nil
|
||||
}
|
||||
|
||||
func validateLocalDrainURL(raw string) error {
|
||||
parsed, err := url.Parse(raw)
|
||||
if err != nil || (parsed.Scheme != "http" && parsed.Scheme != "https") || parsed.Host == "" || parsed.Path == "" || parsed.User != nil || parsed.RawQuery != "" || parsed.Fragment != "" {
|
||||
return fmt.Errorf("drain URL must be a loopback HTTP endpoint")
|
||||
}
|
||||
host := parsed.Hostname()
|
||||
if host != "localhost" {
|
||||
ip := net.ParseIP(host)
|
||||
if ip == nil || !ip.IsLoopback() {
|
||||
return fmt.Errorf("drain URL must be a loopback HTTP endpoint")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start launches the process and marks Agones Ready only after the explicit
|
||||
// readiness probe succeeds. No stdout/log scraping is used. With no SDK URL,
|
||||
// this is direct/Compose mode and the command is simply started.
|
||||
|
||||
@@ -167,3 +167,16 @@ func TestAssignedEndpointRejectsMalformedAddressAndPort(t *testing.T) {
|
||||
server.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSupervisorRejectsRemoteOrPartialDrainConfiguration(t *testing.T) {
|
||||
for _, config := range []Config{
|
||||
{Command: []string{"/bin/sh", "-c", "exit 0"}, DrainURL: "https://example.com/drain", DrainToken: "token-1234567890123456"},
|
||||
{Command: []string{"/bin/sh", "-c", "exit 0"}, DrainURL: "http://127.0.0.1/drain"},
|
||||
{Command: []string{"/bin/sh", "-c", "exit 0"}, DrainToken: "token-1234567890123456"},
|
||||
{Command: []string{"/bin/sh", "-c", "exit 0"}, DrainURL: "http://127.0.0.1/drain?token=leaked", DrainToken: "token-1234567890123456"},
|
||||
} {
|
||||
if _, err := New(config); err == nil {
|
||||
t.Fatalf("unsafe drain configuration accepted: %+v", config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user