From b2a9564f8edb53d645e7d11732ca95755bb8ad4a Mon Sep 17 00:00:00 2001 From: RW Date: Wed, 30 Jul 2025 09:02:46 +0200 Subject: [PATCH 1/4] Add basicauth config migrator --- cmd/internal/migrations/lists.go | 1 + cmd/internal/migrations/v3/common.go | 51 +++++++++++++++++++++++ cmd/internal/migrations/v3/common_test.go | 29 +++++++++++++ 3 files changed, 81 insertions(+) diff --git a/cmd/internal/migrations/lists.go b/cmd/internal/migrations/lists.go index 53bd1e8..5d7f49b 100644 --- a/cmd/internal/migrations/lists.go +++ b/cmd/internal/migrations/lists.go @@ -59,6 +59,7 @@ var Migrations = []Migration{ v3migrations.MigrateSessionExtractor, v3migrations.MigrateTimeoutConfig, v3migrations.MigrateBasicauthAuthorizer, + v3migrations.MigrateBasicauthConfig, v3migrations.MigrateReqHeaderParser, MigrateGoVersion("1.24"), }, diff --git a/cmd/internal/migrations/v3/common.go b/cmd/internal/migrations/v3/common.go index 33618ee..fa4dddb 100644 --- a/cmd/internal/migrations/v3/common.go +++ b/cmd/internal/migrations/v3/common.go @@ -1,6 +1,8 @@ package v3 import ( + "crypto/sha256" + "encoding/base64" "fmt" "regexp" "strconv" @@ -12,6 +14,11 @@ import ( "github.com/gofiber/cli/cmd/internal" ) +var ( + hexRe = regexp.MustCompile(`^[0-9a-fA-F]{64}$`) + b64Re = regexp.MustCompile(`^[A-Za-z0-9+/]{43}=?$|^[A-Za-z0-9+/]{44}$`) +) + func MigrateHandlerSignatures(cmd *cobra.Command, cwd string, _, _ *semver.Version) error { sigReplacer := strings.NewReplacer("*fiber.Ctx", "fiber.Ctx") @@ -715,6 +722,50 @@ func MigrateBasicauthAuthorizer(cmd *cobra.Command, cwd string, _, _ *semver.Ver return nil } +// MigrateBasicauthConfig adapts basicauth configuration to the new API +// * removes ContextUsername and ContextPassword fields +// * hashes plaintext Users entries using SHA-256 +func MigrateBasicauthConfig(cmd *cobra.Command, cwd string, _, _ *semver.Version) error { + reCtxUser := regexp.MustCompile(`\s*ContextUsername:\s*[^,]+,?\n`) + reCtxPass := regexp.MustCompile(`\s*ContextPassword:\s*[^,]+,?\n`) + reUsers := regexp.MustCompile(`Users:\s*map\[string\]string{([^}]*)}`) + reEntry := regexp.MustCompile(`("[^"]+")\s*:\s*"([^"]*)"`) + + err := internal.ChangeFileContent(cwd, func(content string) string { + content = reCtxUser.ReplaceAllString(content, "") + content = reCtxPass.ReplaceAllString(content, "") + + content = reUsers.ReplaceAllStringFunc(content, func(m string) string { + sub := reUsers.FindStringSubmatch(m) + if len(sub) < 2 { + return m + } + body := reEntry.ReplaceAllStringFunc(sub[1], func(s string) string { + es := reEntry.FindStringSubmatch(s) + if len(es) < 3 { + return s + } + pwd := es[2] + if strings.HasPrefix(pwd, "{") || strings.HasPrefix(pwd, "$2") || hexRe.MatchString(pwd) || b64Re.MatchString(pwd) { + return s + } + sum := sha256.Sum256([]byte(pwd)) + hashed := base64.StdEncoding.EncodeToString(sum[:]) + return fmt.Sprintf("%s: \"{SHA256}%s\"", es[1], hashed) + }) + return "Users: map[string]string{" + body + "}" + }) + + return content + }) + if err != nil { + return fmt.Errorf("failed to migrate basicauth config: %w", err) + } + + cmd.Println("Migrating basicauth configs") + return nil +} + // MigrateCacheConfig updates cache middleware configuration fields func MigrateCacheConfig(cmd *cobra.Command, cwd string, _, _ *semver.Version) error { err := internal.ChangeFileContent(cwd, func(content string) string { diff --git a/cmd/internal/migrations/v3/common_test.go b/cmd/internal/migrations/v3/common_test.go index 89a24ba..2982128 100644 --- a/cmd/internal/migrations/v3/common_test.go +++ b/cmd/internal/migrations/v3/common_test.go @@ -883,6 +883,35 @@ var _ = basicauth.New(basicauth.Config{ assert.Contains(t, buf.String(), "Migrating basicauth authorizer") } +func Test_MigrateBasicauthConfig(t *testing.T) { + t.Parallel() + + dir, err := os.MkdirTemp("", "mbasiccfg") + require.NoError(t, err) + defer func() { require.NoError(t, os.RemoveAll(dir)) }() + + file := writeTempFile(t, dir, `package main +import ( + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/basicauth" +) +var _ = basicauth.New(basicauth.Config{ + Users: map[string]string{"john": "doe"}, + ContextUsername: "u", + ContextPassword: "p", +})`) + + var buf bytes.Buffer + cmd := newCmd(&buf) + require.NoError(t, v3.MigrateBasicauthConfig(cmd, dir, nil, nil)) + + content := readFile(t, file) + assert.NotContains(t, content, "ContextUsername") + assert.NotContains(t, content, "ContextPassword") + assert.Contains(t, content, "{SHA256}eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=") + assert.Contains(t, buf.String(), "Migrating basicauth configs") +} + func Test_MigrateShutdownHook(t *testing.T) { t.Parallel() From b8f1e4ac1db54fb674895933a8e9b3cf5da125c2 Mon Sep 17 00:00:00 2001 From: RW Date: Wed, 30 Jul 2025 09:06:18 +0200 Subject: [PATCH 2/4] Update cmd/internal/migrations/v3/common.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- cmd/internal/migrations/v3/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/internal/migrations/v3/common.go b/cmd/internal/migrations/v3/common.go index fa4dddb..6651e6f 100644 --- a/cmd/internal/migrations/v3/common.go +++ b/cmd/internal/migrations/v3/common.go @@ -729,7 +729,7 @@ func MigrateBasicauthConfig(cmd *cobra.Command, cwd string, _, _ *semver.Version reCtxUser := regexp.MustCompile(`\s*ContextUsername:\s*[^,]+,?\n`) reCtxPass := regexp.MustCompile(`\s*ContextPassword:\s*[^,]+,?\n`) reUsers := regexp.MustCompile(`Users:\s*map\[string\]string{([^}]*)}`) - reEntry := regexp.MustCompile(`("[^"]+")\s*:\s*"([^"]*)"`) + reEntry := regexp.MustCompile(`("[^"]+")\s*:\s*"((?:[^"\\]|\\.)*)"`) err := internal.ChangeFileContent(cwd, func(content string) string { content = reCtxUser.ReplaceAllString(content, "") From a1f537ab2c95af5b412a4287263c8e9f74a06eb6 Mon Sep 17 00:00:00 2001 From: RW Date: Wed, 30 Jul 2025 09:07:21 +0200 Subject: [PATCH 3/4] Update cmd/internal/migrations/v3/common.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- cmd/internal/migrations/v3/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/internal/migrations/v3/common.go b/cmd/internal/migrations/v3/common.go index 6651e6f..2e92f18 100644 --- a/cmd/internal/migrations/v3/common.go +++ b/cmd/internal/migrations/v3/common.go @@ -16,7 +16,7 @@ import ( var ( hexRe = regexp.MustCompile(`^[0-9a-fA-F]{64}$`) - b64Re = regexp.MustCompile(`^[A-Za-z0-9+/]{43}=?$|^[A-Za-z0-9+/]{44}$`) + b64Re = regexp.MustCompile(`^[A-Za-z0-9+/]{43}=?$`) ) func MigrateHandlerSignatures(cmd *cobra.Command, cwd string, _, _ *semver.Version) error { From 0f7a5f9613776d4e4b36c421cf11b5671c49af22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Wed, 30 Jul 2025 09:09:40 +0200 Subject: [PATCH 4/4] format file --- cmd/internal/migrations/v3/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/internal/migrations/v3/common.go b/cmd/internal/migrations/v3/common.go index 2e92f18..e6b177c 100644 --- a/cmd/internal/migrations/v3/common.go +++ b/cmd/internal/migrations/v3/common.go @@ -729,7 +729,7 @@ func MigrateBasicauthConfig(cmd *cobra.Command, cwd string, _, _ *semver.Version reCtxUser := regexp.MustCompile(`\s*ContextUsername:\s*[^,]+,?\n`) reCtxPass := regexp.MustCompile(`\s*ContextPassword:\s*[^,]+,?\n`) reUsers := regexp.MustCompile(`Users:\s*map\[string\]string{([^}]*)}`) - reEntry := regexp.MustCompile(`("[^"]+")\s*:\s*"((?:[^"\\]|\\.)*)"`) + reEntry := regexp.MustCompile(`("[^"]+")\s*:\s*"((?:[^"\\]|\\.)*)"`) err := internal.ChangeFileContent(cwd, func(content string) string { content = reCtxUser.ReplaceAllString(content, "")