diff --git a/controlplane/serverconfig/paper.go b/controlplane/serverconfig/paper.go new file mode 100644 index 00000000..a2b25d36 --- /dev/null +++ b/controlplane/serverconfig/paper.go @@ -0,0 +1,52 @@ +package serverconfig + +import ( + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spacechunks/explorer/controlplane/blob" +) + +/* +proxies: + bungee-cord: + online-mode: true + proxy-protocol: false + velocity: + enabled: false + online-mode: true + secret: "" +*/ + +type paperGlobal struct { + Proxies proxiesConfig `json:"proxies"` +} + +type proxiesConfig struct { + ProxyProtocol bool `json:"proxy-protocol"` + Velocity struct { + Enabled bool `json:"enabled"` + OnlineMode bool `json:"online-mode"` + Secret string `json:"secret"` + } +} + +func sanatizePaperGlobal(data []byte) ([]byte, error) { + var global paperGlobal + if err := yaml.Unmarshal(data, &blob.Object{}); err != nil { + return nil, fmt.Errorf("unmarshal: %w", err) + } + + global.Proxies.ProxyProtocol = false + + global.Proxies.Velocity.Enabled = true + global.Proxies.Velocity.OnlineMode = true + global.Proxies.Velocity.Secret = "" + + ret, err := yaml.Marshal(global) + if err != nil { + return nil, fmt.Errorf("marshal: %w", err) + } + + return ret, nil +} diff --git a/controlplane/serverconfig/paper_internal_test.go b/controlplane/serverconfig/paper_internal_test.go new file mode 100644 index 00000000..7e21372c --- /dev/null +++ b/controlplane/serverconfig/paper_internal_test.go @@ -0,0 +1,46 @@ +package serverconfig + +import ( + "testing" + + "github.com/goccy/go-yaml" + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" +) + +func TestPaperConfigAdjustments(t *testing.T) { + input := ` +proxies: + bungee-cord: + online-mode: true + proxy-protocol: true + velocity: + enabled: false + online-mode: false + secret: "blalala" +` + expectedCfg := paperGlobal{ + Proxies: proxiesConfig{ + ProxyProtocol: false, + Velocity: struct { + Enabled bool `json:"enabled"` + OnlineMode bool `json:"online-mode"` + Secret string `json:"secret"` + }{ + Enabled: true, + OnlineMode: true, + Secret: "", + }, + }, + } + + expectedYaml, err := yaml.Marshal(expectedCfg) + require.NoError(t, err) + + actual, err := sanatizePaperGlobal([]byte(input)) + require.NoError(t, err) + + if d := cmp.Diff(string(expectedYaml), string(actual)); d != "" { + t.Fatalf("mismatch (-want +got):\n%s", d) + } +} diff --git a/controlplane/serverconfig/sanatize.go b/controlplane/serverconfig/sanatize.go new file mode 100644 index 00000000..b1a457d2 --- /dev/null +++ b/controlplane/serverconfig/sanatize.go @@ -0,0 +1,60 @@ +package serverconfig + +import ( + "fmt" + "io/fs" + "os" +) + +type sanatize func(data []byte) ([]byte, error) + +var sanatizers map[string]sanatize + +func init() { + sanatizers = map[string]sanatize{ + "server.properties": sanatizeServerProperties, + "config/paper-global.yml": sanatizePaperGlobal, + } +} + +func SanitizeConfigs(root *os.Root) error { + if err := fs.WalkDir(root.FS(), ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + sanatize, ok := sanatizers[path] + if !ok { + return nil + } + + data, err := root.ReadFile(path) + if err != nil { + return fmt.Errorf("failed to read file: %w", err) + } + + sanatized, err := sanatize(data) + if err != nil { + return fmt.Errorf("sanatize file %s: %w", path, err) + } + + info, err := d.Info() + if err != nil { + return fmt.Errorf("file info %s: %w", path, err) + } + + if err := root.WriteFile(path, sanatized, info.Mode()); err != nil { + return fmt.Errorf("write file %s: %w", path, err) + } + + return nil + }); err != nil { + return err + } + + return nil +} diff --git a/controlplane/serverconfig/sanatize_test.go b/controlplane/serverconfig/sanatize_test.go new file mode 100644 index 00000000..610b57d0 --- /dev/null +++ b/controlplane/serverconfig/sanatize_test.go @@ -0,0 +1,89 @@ +package serverconfig_test + +import ( + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/spacechunks/explorer/controlplane/serverconfig" + "github.com/stretchr/testify/require" +) + +func TestSanatizeConfigs(t *testing.T) { + root, err := os.OpenRoot(t.TempDir()) + require.NoError(t, err) + + paperGlobal := ` +proxies: + bungee-cord: + online-mode: true + proxy-protocol: true + velocity: + enabled: false + online-mode: false + secret: "blalala" +` + + err = root.Mkdir("config", os.ModePerm) + require.NoError(t, err) + + err = root.WriteFile("config/paper-global.yml", []byte(paperGlobal), os.ModePerm) + require.NoError(t, err) + + properties := ` +#Minecraft server properties +#Mon Mar 09 17:21:18 CET 2026 +log-ips=true +management-server-allowed-origins= +management-server-enabled=false +management-server-host=1.1.1.1 +management-server-port=1337 +management-server-secret=wrong +management-server-tls-enabled=false +online-mode=true +server-ip= +server-port=1337 +use-native-transport=true +` + + err = root.WriteFile("server.properties", []byte(properties), os.ModePerm) + require.NoError(t, err) + + err = serverconfig.SanitizeConfigs(root) + require.NoError(t, err) + + expectedPaperGlobal := `proxies: + proxy-protocol: false + velocity: + enabled: true + online-mode: true + secret: "" +` + + expectedProperties := `log-ips = false +management-server-allowed-origins = * +management-server-enabled = true +management-server-host = localhost +management-server-port = 26656 +management-server-secret = change-me-later +management-server-tls-enabled = false +online-mode = false +server-ip = 0.0.0.0 +server-port = 25565 +use-native-transport = true +` + + actualPaperGlobal, err := root.ReadFile("config/paper-global.yml") + require.NoError(t, err) + + actualProperties, err := root.ReadFile("server.properties") + require.NoError(t, err) + + if d := cmp.Diff(expectedPaperGlobal, string(actualPaperGlobal)); d != "" { + t.Fatalf("mismatch (-want +got):\n%s", d) + } + + if d := cmp.Diff(expectedProperties, string(actualProperties)); d != "" { + t.Fatalf("mismatch (-want +got):\n%s", d) + } +} diff --git a/controlplane/serverconfig/vanilla.go b/controlplane/serverconfig/vanilla.go new file mode 100644 index 00000000..056a0ed6 --- /dev/null +++ b/controlplane/serverconfig/vanilla.go @@ -0,0 +1,36 @@ +package serverconfig + +import ( + "fmt" + + "github.com/magiconair/properties" +) + +func sanatizeServerProperties(data []byte) ([]byte, error) { + props, err := properties.LoadString(string(data)) + if err != nil { + return nil, fmt.Errorf("parse properties: %w", err) + } + + vals := map[string]any{ + "server-ip": "0.0.0.0", + "server-port": 25565, + "management-server-allowed-origins": "*", + "management-server-enabled": true, + "management-server-host": "localhost", + "management-server-port": 26656, + "management-server-secret": "change-me-later", + "management-server-tls-enabled": false, + "online-mode": false, + "log-ips": false, + "use-native-transport": true, + } + + for k, v := range vals { + if err := props.SetValue(k, v); err != nil { + return nil, fmt.Errorf("set %s: %w", k, err) + } + } + + return []byte(props.String()), nil +} diff --git a/controlplane/serverconfig/vanilla_internal_test.go b/controlplane/serverconfig/vanilla_internal_test.go new file mode 100644 index 00000000..c3a9e1e6 --- /dev/null +++ b/controlplane/serverconfig/vanilla_internal_test.go @@ -0,0 +1,43 @@ +package serverconfig + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" +) + +func TestMutateProperties(t *testing.T) { + input := `#Minecraft server properties +#Mon Mar 09 17:21:18 CET 2026 +log-ips=true +management-server-allowed-origins= +management-server-enabled=false +management-server-host=1.1.1.1 +management-server-port=1337 +management-server-secret=wrong +management-server-tls-enabled=false +online-mode=true +server-ip= +server-port=1337 +use-native-transport=true +` + expected := `log-ips = false +management-server-allowed-origins = * +management-server-enabled = true +management-server-host = localhost +management-server-port = 26656 +management-server-secret = change-me-later +management-server-tls-enabled = false +online-mode = false +server-ip = 0.0.0.0 +server-port = 25565 +use-native-transport = true +` + actual, err := sanatizeServerProperties([]byte(input)) + require.NoError(t, err) + + if d := cmp.Diff(expected, string(actual)); d != "" { + t.Fatalf("mismatch (-want +got):\n%s", d) + } +} diff --git a/controlplane/worker/create_image.go b/controlplane/worker/create_image.go index e6d5888a..7f69c132 100644 --- a/controlplane/worker/create_image.go +++ b/controlplane/worker/create_image.go @@ -32,6 +32,7 @@ import ( "github.com/spacechunks/explorer/controlplane/chunk" "github.com/spacechunks/explorer/controlplane/job" "github.com/spacechunks/explorer/controlplane/resource" + "github.com/spacechunks/explorer/controlplane/serverconfig" "github.com/spacechunks/explorer/internal/file" "github.com/spacechunks/explorer/internal/image" "github.com/spacechunks/explorer/internal/tarhelper" @@ -152,7 +153,14 @@ func (w *CreateImageWorker) Work(ctx context.Context, riverJob *river.Job[job.Cr return fmt.Errorf("download missing: %w", err) } - // TODO: adjust configs + rt, err := os.OpenRoot(serverRootDir) + if err != nil { + return fmt.Errorf("open root: %w", err) + } + + if err := serverconfig.SanitizeConfigs(rt); err != nil { + return fmt.Errorf("sanitize configs: %w", err) + } // it is VERY important we specify the parent of the server root directory, // because only paths starting INSIDE the passed directory are preserved. @@ -162,8 +170,6 @@ func (w *CreateImageWorker) Work(ctx context.Context, riverJob *river.Job[job.Cr return fmt.Errorf("append layer: %w", err) } - // FIXME: if we implement users add user id to ref - // => //: ref := fmt.Sprintf("%s/%s:base", riverJob.Args.OCIRegistry, riverJob.Args.FlavorVersionID) if err := w.imgService.Push(ctx, img, ref); err != nil { diff --git a/go.mod b/go.mod index 8b9ddacb..bee2ef49 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/jackc/pgx/v5 v5.7.4 github.com/johannesboyne/gofakes3 v0.0.0-20250825084532-6555d310c473 github.com/lestrrat-go/jwx/v3 v3.0.12 + github.com/magiconair/properties v1.8.10 github.com/peterbourgon/ff/v3 v3.4.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pkg/errors v0.9.1 @@ -124,7 +125,6 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/lmittmann/tint v1.0.7 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/magiconair/properties v1.8.10 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect