-
Notifications
You must be signed in to change notification settings - Fork 21
feat: add keyauth migrator #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1004,3 +1004,87 @@ func MigrateSessionExtractor(cmd *cobra.Command, cwd string, _, _ *semver.Versio | |
| cmd.Println("Migrating session KeyLookup config") | ||
| return nil | ||
| } | ||
|
|
||
| // MigrateKeyAuthConfig updates keyauth middleware configuration to use Extractor | ||
| // instead of KeyLookup/AuthScheme and removes the deprecated fields. | ||
| func MigrateKeyAuthConfig(cmd *cobra.Command, cwd string, _, _ *semver.Version) error { | ||
| reConfig := regexp.MustCompile(`keyauth\.Config{[^}]*}`) | ||
| reKeyLookup := regexp.MustCompile(`(?m)(\s*)KeyLookup:\s*("[^"]+")(,?)(\n?)`) | ||
| reAuthScheme := regexp.MustCompile(`(?m)\s*AuthScheme:\s*([^,\n]+)`) | ||
|
|
||
| err := internal.ChangeFileContent(cwd, func(content string) string { | ||
| return reConfig.ReplaceAllStringFunc(content, func(cfg string) string { | ||
| keyMatch := reKeyLookup.FindStringSubmatch(cfg) | ||
| if len(keyMatch) < 5 { | ||
| // remove AuthScheme if present | ||
| return removeConfigField(cfg, "AuthScheme") | ||
| } | ||
|
|
||
| indent := keyMatch[1] | ||
| val := strings.TrimSpace(keyMatch[2]) | ||
| comma := keyMatch[3] | ||
| newline := keyMatch[4] | ||
|
|
||
| if uq, err := strconv.Unquote(val); err == nil { | ||
| val = uq | ||
| } | ||
|
|
||
| scheme := "Bearer" | ||
| if am := reAuthScheme.FindStringSubmatch(cfg); len(am) > 1 { | ||
| scheme = strings.TrimSpace(am[1]) | ||
| if uq, err := strconv.Unquote(scheme); err == nil { | ||
| scheme = uq | ||
| } | ||
| } | ||
|
|
||
|
Comment on lines
+1032
to
+1039
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not force-quote AuthScheme; preserve raw expressions to avoid breaking variable-based schemes If AuthScheme is provided as a variable or const (not a string literal), unquoting then re-quoting with %q will turn the identifier into a literal string of its name. This changes behavior. Instead, keep the raw matched expression (quoted or not) and only default to a quoted "Bearer" when missing. Apply this diff to preserve AuthScheme expressions and fix the FromAuthHeader call: - scheme := "Bearer"
- if am := reAuthScheme.FindStringSubmatch(cfg); len(am) > 1 {
- scheme = strings.TrimSpace(am[1])
- if uq, err := strconv.Unquote(scheme); err == nil {
- scheme = uq
- }
- }
+ // Preserve raw AuthScheme expression if present (supports literals and identifiers).
+ // Default to a quoted "Bearer" when not provided.
+ schemeArg := strconv.Quote("Bearer")
+ if am := reAuthScheme.FindStringSubmatch(cfg); len(am) > 1 {
+ schemeArg = strings.TrimSpace(am[1])
+ }
@@
- if strings.EqualFold(header, "Authorization") {
- extractors = append(extractors, fmt.Sprintf("keyauth.FromAuthHeader(%q, %q)", header, scheme))
+ if strings.EqualFold(header, "Authorization") {
+ extractors = append(extractors, fmt.Sprintf("keyauth.FromAuthHeader(%q, %s)", header, schemeArg))Also applies to: 1045-1052 |
||
| parts := strings.Split(val, ",") | ||
| var extractors []string | ||
| for _, p := range parts { | ||
| p = strings.TrimSpace(p) | ||
| switch { | ||
| case strings.HasPrefix(p, "header:"): | ||
| header := strings.TrimPrefix(p, "header:") | ||
| if strings.EqualFold(header, "Authorization") { | ||
| extractors = append(extractors, fmt.Sprintf("keyauth.FromAuthHeader(%q, %q)", header, scheme)) | ||
| } else { | ||
| extractors = append(extractors, fmt.Sprintf("keyauth.FromHeader(%q)", header)) | ||
| } | ||
| case strings.HasPrefix(p, "query:"): | ||
| extractors = append(extractors, fmt.Sprintf("keyauth.FromQuery(%q)", strings.TrimPrefix(p, "query:"))) | ||
| case strings.HasPrefix(p, "param:"): | ||
| extractors = append(extractors, fmt.Sprintf("keyauth.FromParam(%q)", strings.TrimPrefix(p, "param:"))) | ||
| case strings.HasPrefix(p, "form:"): | ||
| extractors = append(extractors, fmt.Sprintf("keyauth.FromForm(%q)", strings.TrimPrefix(p, "form:"))) | ||
| case strings.HasPrefix(p, "cookie:"): | ||
| extractors = append(extractors, fmt.Sprintf("keyauth.FromCookie(%q)", strings.TrimPrefix(p, "cookie:"))) | ||
| default: | ||
| // unrecognized source; remove field and return | ||
| cfg = removeConfigField(cfg, "AuthScheme") | ||
| return removeConfigField(cfg, "KeyLookup") | ||
| } | ||
| } | ||
|
|
||
| extractor := "" | ||
| if len(extractors) == 1 { | ||
| extractor = extractors[0] | ||
| } else if len(extractors) > 1 { | ||
| extractor = fmt.Sprintf("keyauth.Chain(%s)", strings.Join(extractors, ", ")) | ||
| } | ||
|
|
||
| cfg = removeConfigField(cfg, "AuthScheme") | ||
| if extractor == "" { | ||
| return removeConfigField(cfg, "KeyLookup") | ||
| } | ||
|
|
||
| newField := fmt.Sprintf("%sExtractor: %s%s%s", indent, extractor, comma, newline) | ||
| cfg = reKeyLookup.ReplaceAllString(cfg, newField) | ||
| return cfg | ||
| }) | ||
| }) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to migrate keyauth configs: %w", err) | ||
| } | ||
|
|
||
| cmd.Println("Migrating keyauth middleware configs") | ||
| return nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The regex
keyauth\.Config{[^}]*}is not robust enough to handle struct literals that contain nested blocks with braces, such as function literals (e.g., for aValidatorfield). The[^}]*pattern will stop at the first closing brace}it encounters, which can lead to an incomplete match and broken code after migration.For example, this valid configuration would be migrated incorrectly:
To fix this, you should use a more robust method to find the entire
keyauth.Configstruct literal. Instead of a single regex, you could find the startkeyauth.Config{and then programmatically scan for the matching closing brace, taking into account nested braces and strings, similar to the logic in theremoveConfigFieldfunction.