fix(AF-936): scope schema introspection to the caller's allow-list - #1088
Merged
Merged
Conversation
DefaultSampleDataService now matches its target through core.api.AllowedTables, so a bare allowed_tables entry no longer admits a schema-qualified preview the query gate rejects; a bare entry covers a qualified target only when the name is unique in the view (#936 rule). DefaultQueryDryRunService drops its duplicate normalizer too. Refs #1089
Contributor
Contributor
Coverage Report for Frontend Coverage (frontend)
File CoverageNo changed files found. |
Contributor
Contributor
Backend Code Coverage
|
…ow-list fix(AF-1089): match table preview allow-list to the query gate
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.
Closes #936
What
GET /datasources/{id}/schema— and every user-path caller ofDatasourceAdminService.introspectSchema(editor schema tree/autocomplete, table preview, AI analyze-preview, text-to-SQL, MCPget_datasource_schema/validate_sql) — is now scoped to the caller's effective permission for non-admins:allowed_schemas/allowed_tablesare dropped (both empty = unrestricted, as in enforcement);denied_columnsare dropped;404 DATASOURCE_NOT_FOUND, before any connection is opened.Admins,
introspectSchemaForSystem(async AI analysis, discovery, drift, snapshots, replay) and the JIT request-form endpoint are unchanged. Query enforcement is unchanged.How
core.api.AllowedTables— the allow-listnormalize/coveringEntrymoved out ofworkflow.internal.DatasourcePermissionChecker(which now delegates, byte-for-byte), socorecan reuse the gate's matcher.core.api.DeniedColumns.deniesColumn— per-column check on the existing proxy: column-level authorization — block, not just mask #935 matching rule.core.internal.SchemaViewPermissionFilter— pure filter. Fails closed where the view cannot know what the gate allows: a bareallowed_tablesentry shows a table only when its name is unique across schemas (qualify the entry otherwise). Catalog-qualified entries (proj.ds.t,db.dbo.t) match their trailingschema.table.DatasourceAdminServiceImpl.introspectSchemaresolvesDatasourceUserPermissionLookupService.findForand applies the filter.Docs / website
docs/04-api-spec.md,docs/05-backend.md,docs/07-security.md,docs/13-mcp.mdwebsite/docs/configuration/datasources/index.html(+ regeneratedhelp-corpus/)Verification
mvn -o verify -Pcoverage: 10,241 tests, 0 failures (first commit). The follow-up commit re-ranSchemaViewPermissionFilterTest,DatasourceAdminServiceImplTest,DatasourceConnectionTestIntegrationTest(real Postgres: restricted analyst sees onlycustomerswithoutemail; admin sees everything) andDefaultSampleDataServiceTest, all green.ApplicationModulesTest,ApiPackageDependencyTest, spotless, checkstyle, the help-corpus drift check and the website guard suites all pass (af-verifier).Review notes
Four reviewers ran (af-verifier, af-reviewer, af-java-reviewer, af-content-reviewer). Fixed in the second commit:
Concerns that remain, for a human to weigh:
bucket.scope.collectionwhile its view names schemas by scope; Elasticsearch uses index patterns. This only degrades what they see (enforcement is unchanged). Documented as a limitation.DefaultSampleDataService.targetAllowedaccepts a bareallowed_tablesentry for a table in any schema. So the table preview can readarchive.ordersunderallowed_tables=[orders]even though the query gate rejectsarchive.orders. This is not introduced here; flagged for a separate fix.deniesColumnre-normalizes the deny list on each call;DefaultSampleDataService/DefaultQueryDryRunServicestill have privatenormalizeListcopies.