Skip to content

feat(REQ-925): clonedInformationSchema mirror-schema support for restricted-access SDR - #176

Draft
vaibhavatlan wants to merge 3 commits into
mainfrom
feat/req-925-cloned-information-schema
Draft

feat(REQ-925): clonedInformationSchema mirror-schema support for restricted-access SDR#176
vaibhavatlan wants to merge 3 commits into
mainfrom
feat/req-925-cloned-information-schema

Conversation

@vaibhavatlan

Copy link
Copy Markdown
Collaborator

Summary

Re-raises the REQ-925 feature (originally closed PR #121) on the current main. The original branch could not be rebased — main was refactored since it branched (app/clients.pyapp/client.py, app/handlers/mysql.pyapp/handler.py) and the repo history was rewritten — so this is a clean re-implementation sourced from the preserved branch and re-fitted to the current structure + SDK 3.15.1.

Adds a Custom Control Config option that routes every INFORMATION_SCHEMA query through a customer-managed mirror schema (e.g. atlan_meta). Solves the restricted-access SDR blocker: in MySQL, granting SELECT on INFORMATION_SCHEMA implicitly grants SELECT on every underlying user table, which violates some customers' security policies.

Backward compatible: with no control-config supplied, rendered SQL is byte-identical to today.

How it works

  1. DBA runs scripts/setup_information_schema_mirror.sql once — creates a mirror schema with passthrough views over INFORMATION_SCHEMA and a reader user with SELECT only on the mirror.
  2. In the workflow UI → Advanced Config → Control Config → Custom: { "clonedInformationSchema": "atlan_meta" }.
  3. Every metadata query (preflight, fetch_metadata, full extraction) routes through atlan_meta.* instead of information_schema.*.

Changes

  • app/utils.py (new) — resolve_information_schema / resolve_excluded_schemas / extract_control_config; hard identifier validation as a SQL-injection guard.
  • app/sql/* — parametrize information_schema and the system-schema exclusion list.
  • app/mysql.py_prepare_sql / build_task_input / _init_sql_client overrides thread control-config into each extract activity.
  • app/handler.py — per-request resolution for preflight + fetch_metadata.
  • contract/app.pkl + regenerated app/generated/* — Advanced Config UI fields.
  • scripts/setup_information_schema_mirror.sql (new) — one-time DBA setup.
  • Tests — unit (test_utils, test_handler, test_mysql_app) + integration (test_mirror_schema).

Notes for reviewers

  • Scope is the mirror-schema feature only. The original branch also carried unrelated ae-workflow.sh DAG-contract edits + test_dag_contracts.py and a tenant-deploy.yaml/app/templates/workflow.json — those were not part of this feature (and touched files since pruned/scrubbed), so they're intentionally omitted.
  • Original authorship preserved via Co-Authored-By.

Test plan

  • pytest tests/unit — 218 passed locally
  • poe generate leaves the tree clean
  • ruff check (repo rule set) passes
  • CI green (incl. integration via testcontainers)

🤖 Generated with Claude Code

…cess SDR

Re-implements the internal-ref feature on the current main (the original branch
predated a handler/client refactor + a history rewrite, so it could not be
rebased mechanically). Sourced from the preserved branch and re-fitted to the
current structure + SDK 3.15.1; unit suite green (218 passed).

Lets customers route every INFORMATION_SCHEMA query through a customer-managed
mirror schema (e.g. atlan_meta), solving the restricted-access blocker where
granting SELECT on INFORMATION_SCHEMA implicitly grants SELECT on every
underlying user table. Backward compatible: with no control-config, rendered
SQL is byte-identical to today.

- app/utils.py: resolve_information_schema / resolve_excluded_schemas /
  extract_control_config, with hard identifier validation (SQL-injection guard).
- app/sql/*: parametrize information_schema + system-schema exclusion list.
- app/mysql.py: _prepare_sql + build_task_input + _init_sql_client overrides
  thread control-config into each extract activity.
- app/handler.py: per-request resolution for preflight + fetch_metadata.
- contract/app.pkl + regenerated app/generated/*: Advanced Config UI fields.
- scripts/setup_information_schema_mirror.sql: one-time DBA setup.
- tests: unit (utils, handler, app) + integration (mirror schema).

Co-Authored-By: AtMrun <121743130+AtMrun@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mothership-reviewer

Copy link
Copy Markdown

👋 Mothership PR Reviewer is ready.

Comment @mothership-reviewer run to start an AI code review.
Or add the label request-mothership-review to this PR.

@github-actions github-actions Bot added the feat New feature label Jun 10, 2026
@snykgituser

snykgituser commented Jun 10, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Tests Summary

Job Status Result
tests ✅ Passed 260 passed, 1 xfailed, 2 warnings in 85.93s (0:01:25)
e2e ⊘ Skipped — add e2e label to trigger (see run)

Overall: ✅ All passed — view run

@vaibhavatlan
vaibhavatlan marked this pull request as draft June 10, 2026 11:06
@github-actions

Copy link
Copy Markdown
Contributor

🛡️ Security Gate Passed

Trivy: 0 | Total: 0 CRITICAL/HIGH | All allowlisted ✅

Run: 27271846045 | Wed, 10 Jun 2026 11:09:31 GMT

@mothership-reviewer mothership-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Superseded by newer review

@mothership-reviewer mothership-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Mothership PR Reviewer — Approve

Score Decision Risk Blocking Critical High
74/100 ✅ Approve 🔺 Elevated 0 0 0

Elevated risk — critical/high findings or weak safeguards noted below. Worth a closer look before merging.

This PR implements the clonedInformationSchema mirror-schema feature cleanly. SQL injection is well-guarded by _IDENTIFIER_RE. The Temporal worker-boundary problem (activity vs workflow context) is correctly solved by carrying control-config on the task input, with end-to-end verification in source-side-behavior-verification.md. Test coverage is excellent: unit, integration with testcontainers, and privilege isolation. The handler/activity precedence divergence is intentional and documented. One INFO: allow_unbounded_fields=True is a dead SDK keyword (removed in SDK 3.7.0); the real gu

🔎 Findings (1)

ℹ️ INFO allow_unbounded_fields=True dead SDK keyword; comment misidentifies the actual guard

  • Pattern: dead-sdk-keyword-misleading-comment
  • Category: defensive
  • Confidence: 90%
  • Location: app/mysql.py:150
  • Reachability: internal-only — class definition, not an entry point
  • By-design check: no prior discussion; code is correct via ConfigDict(extra='allow'); dead keyword is documented with type: ignore[call-arg]
  • Verifier: downgraded — Downgraded LOW->INFO: zero runtime impact; 218 tests pass; ConfigDict(extra='allow') is the real guard; type: ignore[call-arg] signals author awareness.
Evidence
class MySQLExtractionInput(ExtractionInput, allow_unbounded_fields=True):  # type: ignore[call-arg]

Suggested fix: Remove allow_unbounded_fields=True (ignored since SDK 3.7.0); update docstring to credit ConfigDict(extra='allow') as the actual safety guard. Also applies to MySQLExtractionTaskInput at line 172.

💪 Strengths (3)
  • Excellent test coverage: unit, integration via testcontainers, and privilege-isolation class validating the security premise end-to-end.
  • SQL injection guard _IDENTIFIER_RE correctly enforces MySQL identifier rules: rejects hyphens, semicolons, backticks, and digit-leading names.
  • Temporal worker-boundary problem is documented in code, docstrings, and source-side-behavior-verification.md with a conclusive drop-probe.
📊 Score Breakdown
Dimension Score
Test quality 95%
Defensive coding 88%
Open findings (impact) 97%
📄 Review Metadata

commit: 7f82158, mode: standard, reviewer version: rover-v2, generated: 2026-06-10T11:20:52.850691Z, dispatch: e66405bf-1f2a-4e10-894e-fb0a0623d580

@vaibhavatlan
vaibhavatlan force-pushed the main branch 3 times, most recently from ea213f1 to 09a0659 Compare June 10, 2026 16:35
@vaibhavatlan
vaibhavatlan force-pushed the feat/req-925-cloned-information-schema branch from 7f82158 to d323ce2 Compare June 10, 2026 16:35
@linear

linear Bot commented Jun 10, 2026

Copy link
Copy Markdown
REQ-925 Support custom INFORMATION_SCHEMA mirror schema for MySQL/MariaDB connector (SDR)

Context

Bandwidth's infosec team is blocking SDR adoption for their RDBMS connectors (MariaDB 10.11, SQLDB) because the MySQL connector requires SELECT * on INFORMATION_SCHEMA, which in MySQL means SELECT privilege on the actual underlying data tables. This is a MySQL architectural constraint — not an Atlan choice — but their infosec policy won't allow it.

Slack thread: https://atlanhq.slack.com/archives/CSC46LFAB/p1763583889911889

Customer Proposal

Bandwidth proposed a custom curated view workaround: create views wrapping the INFORMATION_SCHEMA content in a separate schema, grant SELECT only on those views, and point Atlan's connector at those instead of the native INFORMATION_SCHEMA.

Current State

The MySQL connector (atlanhq/atlan-mysql-app) does not support this today. All SQL queries in app/sql/ have hardcoded references to information_schema.* tables with no templating mechanism for schema replacement.

Precedent: Redshift Cloned Schema

The Redshift connector (atlanhq/atlan-redshift-app) already supports exactly this pattern via a clonedPgCatalogSchema configuration in Custom Control Config. It uses {cloned_schema} placeholders in SQL templates that resolve to either the custom schema or the default system schema. Docs reference.

What the MySQL Connector Queries

The connector queries these INFORMATION_SCHEMA tables:

  • SCHEMATA — schema discovery
  • TABLES — table/view metadata (name, type, row count, size)
  • VIEWS — view definitions
  • COLUMNS — column metadata (types, nullability, defaults)
  • KEY_COLUMN_USAGE + TABLE_CONSTRAINTS — PK/FK constraints
  • PARTITIONS — partition metadata
  • ROUTINES — stored procedures/functions

Implementation Scope (Estimated)

Following the Redshift pattern:

  1. Add {cloned_schema} placeholders to all SQL files in app/sql/ (replacing information_schema. prefix)
  2. Implement a resolve_cloned_sql() utility similar to Redshift's app/activities/metadata_extraction/utils.py
  3. Wire up Custom Config / Control Config UI in the crawler workflow template
  4. Document DBA-side setup (creating the mirror schema, materializing views, setting up refresh schedule)
  5. Validate with MariaDB 10.11 specifically (Bandwidth's version)

Requestor

Bandwidth (via David Fisher, Prerna Sharma, Akshay Dhingra)

Review in Linear

@github-actions

Copy link
Copy Markdown
Contributor

🛡️ Security Gate Passed

Trivy: 0 | Total: 0 CRITICAL/HIGH | All allowlisted ✅

Run: 27290743591 | Wed, 10 Jun 2026 16:38:45 GMT

@vaibhavatlan
vaibhavatlan force-pushed the feat/req-925-cloned-information-schema branch from d323ce2 to 10457d3 Compare June 10, 2026 16:55
@github-actions

Copy link
Copy Markdown
Contributor

🛡️ Security Gate Passed

Trivy: 0 | Total: 0 CRITICAL/HIGH | All allowlisted ✅

Run: 27291951531 | Wed, 10 Jun 2026 16:58:29 GMT

@vaibhavatlan
vaibhavatlan force-pushed the feat/req-925-cloned-information-schema branch from 10457d3 to 728783c Compare June 10, 2026 17:11
@github-actions

Copy link
Copy Markdown
Contributor

🛡️ Security Gate Passed

Trivy: 0 | Total: 0 CRITICAL/HIGH | All allowlisted ✅

Run: 27292857371 | Wed, 10 Jun 2026 17:14:19 GMT

@github-actions

Copy link
Copy Markdown
Contributor

🛡️ Security Gate Passed

Trivy: 0 | Total: 0 CRITICAL/HIGH | All allowlisted ✅

Run: 27294433961 | Wed, 10 Jun 2026 17:41:19 GMT

- Close unterminated string literal in test_mirror_schema.py xfail reason
- Apply ruff-format line wrap to warning log call in mysql.py

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🛡️ Security Gate Passed

Trivy: 0 | Total: 0 CRITICAL/HIGH | All allowlisted ✅

Run: 27295183783 | Wed, 10 Jun 2026 17:54:17 GMT

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants