Skip to content

refactor(wolf-rbac): move header_prefix to route configuration - #13929

Open
shreemaan-abhishek wants to merge 4 commits into
apache:masterfrom
shreemaan-abhishek:refactor/wolf-rbac-config-scope
Open

shreemaan-abhishek wants to merge 4 commits into
apache:masterfrom
shreemaan-abhishek:refactor/wolf-rbac-config-scope

Conversation

@shreemaan-abhishek

@shreemaan-abhishek shreemaan-abhishek commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Description

wolf-rbac reads header_prefix from the matched Consumer, so the identity header namespace is unknown until a Wolf token has been parsed and a Consumer found. A Route therefore cannot clear or own its identity headers deterministically.

This PR:

  • moves header_prefix to the Route/Service configuration (default X-)
  • keeps appid (now required), server, and ssl_verify on the Consumer, since a Wolf appid belongs to one Wolf server; the public APIs (login, change_pwd, user_info) keep resolving them from the Consumer matched by appid
  • clears {prefix}UserId, {prefix}Username, and {prefix}Nickname at the start of rewrite, and through a clear_auth_headers hook that multi-auth calls before evaluating any authenticator
  • sets those headers only after Wolf authorization succeeds
  • rejects a custom header_prefix on a Consumer with a migration message; the old schema default "X-" is accepted and dropped

This is a breaking schema change limited to header_prefix.

Migration

Before upgrading, move a custom header_prefix from each Consumer to every Route/Service using wolf-rbac (including wolf-rbac inside multi-auth), and remove it from the Consumer. appid, server, and ssl_verify stay on the Consumer. Routes exposing the Wolf APIs need only public-api, as before.

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (intentional breaking change for Consumer header_prefix)

@Baoyuantop Baoyuantop left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direction looks good (worth merging after the inline notes). Please address the Consumer schema fail-loud gap and the Attributes table split.

},
},
required = {"appid"},
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this move, leftover Consumer keys server / header_prefix / ssl_verify still validate (JSON Schema allows extra properties by default) but are ignored at runtime — traffic can silently hit the default http://127.0.0.1:12180.

Please fail loud on TYPE_CONSUMER: reject those three fields in check_schema (clearer than only additionalProperties = false, and matches an intentional migration), and add a negative Admin/schema test next to the existing “appid is required” case.

Comment thread docs/en/latest/plugins/wolf-rbac.md Outdated
| appid | string | True | N/A | Consumer application ID configured in Wolf. This field supports saving the value in Secret Manager using the [APISIX Secret](../terminology/secret.md) resource. |
| server | string | False | "http://127.0.0.1:12180" | Route or Service address of the Wolf server. |
| header_prefix | string | False | "X-" | Route or Service prefix for the identity headers added after successful authentication: `{prefix}UserId`, `{prefix}Username`, and `{prefix}Nickname`. |
| ssl_verify | boolean | False | false | Whether to verify the Wolf server's TLS certificate. Configured on a Route or Service. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This table still mixes Consumer (appid) and Route/Service (server, header_prefix, ssl_verify) in one place. Please split into two tables (or add a Scope column), same as other dual-schema auth plugins — otherwise the breaking change is easy to misconfigure.

Comment thread docs/zh/latest/plugins/wolf-rbac.md Outdated
| appid | string | 是 | 无 | Consumer 在 Wolf 中配置的应用 ID。该字段支持使用 [APISIX Secret](../terminology/secret.md) 资源,将值保存在 Secret Manager 中。 |
| server | string | 否 | "http://127.0.0.1:12180" | Route 或 Service 使用的 Wolf 服务地址。 |
| header_prefix | string | 否 | "X-" | Route 或 Service 的身份 HTTP 头前缀。鉴权成功后添加 `{prefix}UserId`、`{prefix}Username` 和 `{prefix}Nickname`。 |
| ssl_verify | boolean | 否 | false | 是否验证 Wolf 服务的 TLS 证书。在 Route 或 Service 上配置。 |

@Baoyuantop Baoyuantop Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the EN Attributes note: please split Consumer vs Route/Service fields into separate tables (or add a Scope column), and keep it consistent with the English docs.

Comment thread apisix/plugins/wolf-rbac.lua Outdated
Comment on lines +298 to +301
function _M.rewrite(conf, ctx)
if not auth_utils.is_running_under_multi_auth(ctx) then
clear_identity_headers(conf, ctx)
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that header_prefix lives on the route, this can be unconditional: clear the route-prefix headers as the very first thing in rewrite, before any early return. Clearing is idempotent, so running it again after multi-auth's pre-clear is harmless, and that lets us drop the is_running_under_multi_auth branch, the clear_identity_headers wrapper (L84-94) and the auth_utils require. Something like:

local identity_headers = {"UserId", "Username", "Nickname"}

function _M.clear_auth_headers(conf, ctx)
    for _, name in ipairs(identity_headers) do
        core.request.set_header(ctx, conf.header_prefix .. name, nil)
    end
end

function _M.rewrite(conf, ctx)
    _M.clear_auth_headers(conf, ctx)
    ...

The clear_auth_headers hook in multi-auth should stay though, since wolf-rbac never runs at all when an earlier auth plugin succeeds.

Comment thread apisix/plugins/wolf-rbac.lua Outdated
Comment thread apisix/plugins/wolf-rbac.lua Outdated
Comment thread apisix/plugins/wolf-rbac.lua Outdated
Comment thread t/plugin/multi-auth.t Outdated



=== TEST 25b: malformed Wolf token does not preserve Route identity headers

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover 25b from the reindex, please renumber.

Comment thread t/plugin/wolf-rbac.t Outdated


=== TEST 3: setup public API route
=== TEST 3b: appid is required in Consumer configuration

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, leftover 3b.

@Baoyuantop Baoyuantop self-assigned this Oct 29, 2026
Only header_prefix moves to the route or service, so identity headers
can be cleared before authentication. server and ssl_verify stay on the
consumer, which lets the public API handlers keep resolving them from
the consumer matched by appid.
@shreemaan-abhishek shreemaan-abhishek changed the title refactor(wolf-rbac): separate route and consumer settings refactor(wolf-rbac): move header_prefix to route configuration Oct 29, 2026
@shreemaan-abhishek

Copy link
Copy Markdown
Contributor Author

@nic-6443 Thanks for the review. I'd like to go with a smaller schema change: move only header_prefix to the route and keep server and ssl_verify on the Consumer. The route-level prefix is all the header cleanup needs, because it's the only value that has to be known before authentication.

All three public API handlers (login, change_pwd, user_info) already look up the Consumer by appid before calling Wolf, so they can read server and ssl_verify from it, as on master.

With server on the route, as in the current PR and the ctx.wolf_rbac_conf approach:

  • every public API route has to enable wolf-rbac only to carry server for the handlers;
  • the plugin has to keep a hard-coded list of public API URIs to skip Wolf auth on those routes, or login would demand a token;
  • when wolf-rbac is nested in multi-auth on a public API route, the handlers return 500 whenever another plugin authenticates first: multi-auth stops at the first success, so Wolf's rewrite never runs and ctx.wolf_rbac_conf is never set. The handler then has no server to call and takes the if not conf branch, which exits with 500 "Missing wolf-rbac configuration".

Keeping server on the Consumer removes all three, along with get_route_plugin_conf, is_wolf_public_api, and the global-rule crash you found. This is now pushed in f046af5.

On the other points:

  • rewrite now clears the route-prefix headers unconditionally as its first step; the is_running_under_multi_auth branch and the wrapper are gone, and the multi-auth pre-clear hook stays.
  • TEST 28 passes without the or default_header_prefix fallbacks, so they are removed: multi-auth's check_schema fills the nested defaults as you said.
  • server keeps its default. Since it now stays on the Consumer, making it required would break every existing Consumer that relies on the default, which is out of scope here. Happy to do it in a follow-up.
  • A custom header_prefix on a Consumer is rejected with a migration message. The old schema stored the default "X-" on every Consumer, so that value is accepted and dropped to keep existing Consumers valid.
  • The leftover 25b/3b labels are fixed.

@membphis membphis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants