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..e6b177c 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}=?$`) +) + 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()