Repository navigation
SOLR-13097: Make core-scoped authorization rules work in Solr standalone mode - #5016
Open
nick-boss-tech wants to merge 11 commits into
Open
nick-boss-tech wants to merge 11 commits into
nick-boss-tech wants to merge 11 commits into
Conversation
…ath, upgrade note and changelog type
…in test String.formatted uses the default locale and is rejected by the forbiddenApis check, which failed the core check step.
nick-boss-tech
force-pushed
the
solr-13097-submit
branch
from
October 4, 2026 05:00
8cc61e0 to
e869956
Compare
janhoy
requested changes
Oct 6, 2026
Contributor
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused implementation, tests, and documentation consistently address the reported authorization gap.
Review effort: Balanced
Findings: None
What changed in this PR
Enables core-scoped authorization rules in standalone Solr by using the serving core name as authorization context.
Changes:
- Authorizes standalone requests against the serving core.
- Adds integration coverage for allowed, denied, and unauthenticated requests.
- Documents the behavioral change in upgrade notes and changelog.
| File | Description |
|---|---|
HttpSolrCall.java |
Supplies the standalone core name during authorization. |
CoreScopedAuthStandaloneTest.java |
Tests core-scoped standalone authorization. |
major-changes-in-solr-11.adoc |
Adds upgrade guidance. |
SOLR-13097.yml |
Records the change. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…tandalone test Adds a v2 /api/cores/<core>/select case through V2HttpCall and a case pinning how a wildcard permission interacts with core-scoped rules: the scoped rule governs its core on its own, and the wildcard decides only for cores no scoped rule governs. Also states in the ref guide that for a distributed request only the core receiving the request is checked.
dsmiley
removed their request for review
October 7, 2026 12:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 AI text below 🤖 (posted on behalf of Nick Shanin)
https://issues.apache.org/jira/browse/SOLR-13097
What happens today
In standalone (non-cloud) Solr, authorization rules in
security.jsonthat are scoped to a specific core do not take effect the way they do in cloud mode: the authorization check runs without the serving core's name as its context, so a rule written for one core does not match, and a user can be allowed on a core that a core-scoped rule was meant to deny them.What this change does
HttpSolrCallnow passes the serving core's name as the collection context for the authorization check in standalone mode, so core-scoped rules apply to the core actually serving the request. Cloud behavior is unchanged. The change is noted in the Solr 10.2 upgrade notes (major-changes-in-solr-10.adoc), and the rule-based authorization ref guide now states that in standalone mode thecollectionpermission value can be the name of a core, and that for a distributed request only the core receiving the request is checked. The upgrade note sits in the Solr 10 upgrade notes because this change is intended for backport tobranch_10x(10.2); if maintainers prefer it main-only, the note can move to the Solr 11 upgrade notes page instead.Proof
CoreScopedAuthStandaloneTest: 5 of 5 pass with this change, verified at head f0e7395; tidy, the Error Prone compile and:solr:core:check -x testpass as well. Added in this round: a v2 request throughV2HttpCall(/api/cores/<core>/selectunder the same core-scoped permission) and a wildcard permission alongside the scoped rules, pinning that a scoped rule governs its core on its own and the wildcard decides only for cores no scoped rule governs. Against base production code the v2 and wildcard cases fail for the reason this PR fixes (3 of 5 methods fail on base under the extended configuration). On base code,testScopedRuleDeniesOtherRolesOnTheCorealso fails in the original configuration: it expects aRemoteSolrExceptiondenying a role scoped to another core, and no exception is thrown (4 failing test executions under randomization).shardsbehavior described in Limits was checked with a temporary probe test (not shipped), re-run at head 4c08aa5 on 2026-10-06 in three authentication configurations: both cores governed withblockUnknownat its default, both cores governed withblockUnknown=false, and the target core ungoverned withblockUnknown=false. The observed outcomes match the Limits text.Limits
Standalone mode only. The authorization context is exactly the serving core's name, so rules scoped to anything other than that name do not match, and renaming or swapping a core moves which scoped rule applies to it. The v2 API path passes the same authorization context, so a v2 request served by a core in standalone mode is authorized against the core name as well; the test covers both the v1
/selectpath and a v2/api/cores/<core>/selectrequest. Requests with no serving core, such as/admin/cores?action=...&core=x, are unchanged by this PR: no core name is added for them, and they are authorized as admin requests, as before. Cloud mode is untouched by this change and is not exercised by the new test.In standalone mode a request that fans out to other cores through the
shardsparameter is authorized here only against the serving core. Authorization in this plugin returns the decision of the first listed name that has a governing permission, so listing every shard core would not subject each one to its own check; the per-core check for a shard happens on the node that serves it. Such sub-requests send no user credentials under BasicAuth with default settings; under JWT authentication the caller's token is forwarded, so the receiving core authenticates and authorizes the actual user. WithblockUnknownat its default (true), the receiving core rejects them at authentication. WithblockUnknown=false, a target core that has a governing permission still denies the credential-free sub-request, at authorization. A target core with no governing permission at all, and no wildcard permission either, can return its documents to the caller in that configuration. That last case is the plugin's designed treatment of names with no configured permission, it behaves the same in cloud mode, and it is not a gap this PR opens.Changelog:
changelog/unreleased/SOLR-13097.ymlAI assistance
AI agents assisted with research, implementation, review, and drafting. Nick Shanin directed the work and takes responsibility for this contribution.