feat(security): add built-in Public role for anonymous dashboard access#36548
Conversation
| PUBLIC_ROLE_PERMISSIONS = { | ||
| # Core dashboard viewing | ||
| ("can_read", "Dashboard"), | ||
| ("can_read", "Chart"), | ||
| ("can_dashboard", "Superset"), | ||
| ("can_slice", "Superset"), | ||
| ("can_explore_json", "Superset"), | ||
| ("can_dashboard_permalink", "Superset"), | ||
| ("can_read", "DashboardPermalinkRestApi"), | ||
| # Dashboard filter interactions | ||
| ("can_read", "DashboardFilterStateRestApi"), | ||
| ("can_write", "DashboardFilterStateRestApi"), | ||
| # API access for chart rendering | ||
| ("can_time_range", "Api"), | ||
| ("can_query_form_data", "Api"), | ||
| ("can_query", "Api"), | ||
| # CSS for dashboard styling | ||
| ("can_read", "CssTemplate"), | ||
| # Embedded dashboard support | ||
| ("can_read", "EmbeddedDashboard"), | ||
| # Datasource metadata for chart rendering | ||
| ("can_get", "Datasource"), | ||
| ("can_external_metadata", "Datasource"), | ||
| ("can_external_metadata_by_name", "Datasource"), | ||
| # Security API for CSRF tokens | ||
| ("can_read", "SecurityRestApi"), | ||
| # Menu and OpenAPI access | ||
| ("can_get", "OpenApi"), | ||
| ("can_get", "MenuApi"), | ||
| } | ||
|
|
There was a problem hiding this comment.
Public is given several permissions that Gamma does not have:
can_read → CssTemplate
can_read → SecurityRestApi
can_get → MenuApi
can_get → OpenApi
can_external_metadata_by_name → Datasource
Because of these, public_perm_set - gamma_perm_set is not empty, so test_public_role_more_restrictive_than_gamma will fail. Either remove these permissions from Public or update the test, but both cannot be true at once.
There was a problem hiding this comment.
Thanks for catching that... I'll take 'em out.
There was a problem hiding this comment.
Actually, I added CssTemplate can_read to Gamma :D
This PR adds a new built-in "Public" role to Superset, designed for anonymous/unauthenticated users who need to view dashboards. The Public role is more restrictive than Gamma and provides sensible defaults for public-facing dashboard deployments. Key features: - New PUBLIC_ROLE_PERMISSIONS set defining minimal dashboard viewing permissions - New _is_public_pvm() method to determine Public role permissions - Public role is now created during sync_role_definitions() - Users can set PUBLIC_ROLE_LIKE = "Public" to use these safe defaults The Public role includes: - Dashboard and chart viewing - Interactive dashboard filters (read + write filter state) - Dashboard permalinks - Embedded dashboard support - Datasource metadata for chart rendering The Public role explicitly excludes: - Write permissions on dashboards, charts, datasets - SQL Lab access - Share functionality - User profile/admin features - Menu access to most features This addresses the concerns raised in #36025 where PUBLIC_ROLE_LIKE = "Gamma" grants excessive permissions including write and delete capabilities that are inappropriate for public access. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test_public_role_permissions and test_public_role_more_restrictive_than_gamma tests were failing because the Public role had no permissions. These tests need sync_role_definitions() to be called first to populate the Public role with its expected permissions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… unset or "Public"
This fixes several test failures caused by the new built-in Public role
overwriting the PUBLIC_ROLE_LIKE configuration:
1. Modified sync_role_definitions() to only call set_role("Public", ...) when
PUBLIC_ROLE_LIKE is not set or is explicitly "Public". When PUBLIC_ROLE_LIKE
is set to another role (e.g., "Gamma"), it uses the legacy copy_role behavior.
2. Added public_role_builtin fixture for tests that need to test the new
minimal Public role permissions.
3. Updated test_public_role_permissions and test_public_role_more_restrictive_than_gamma
to use the public_role_builtin fixture since the test config defaults to
PUBLIC_ROLE_LIKE="Gamma".
4. Added PT004 to ruff ignore list since fixtures referenced by name shouldn't
have leading underscores.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ling
Remove "CssTemplate" from ALPHA_ONLY_VIEW_MENUS so Gamma users can read
CSS templates via API. This is needed for rendering styled dashboards.
The "CSS Templates" menu item remains Alpha-only, so Gamma users won't
see the management UI but will be able to view dashboards that use CSS
templates.
This also fixes test_public_role_more_restrictive_than_gamma which asserts
Public ⊆ Gamma - now both roles have ("can_read", "CssTemplate").
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…t fixtures 1. Add CssTemplate to GAMMA_READ_ONLY_MODEL_VIEWS so Gamma gets can_read but not can_write permissions. This maintains the Alpha-only restriction for write operations while allowing dashboard styling to work for Gamma users. 2. Fix pytest fixture parentheses style (PT001) - remove empty parentheses from @pytest.fixture decorators per ruff 0.9+ rules. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
33e3c2d to
306dbdc
Compare
Remove permissions that aren't strictly necessary for public dashboard viewing to ensure Public is a proper subset of Gamma: - can_external_metadata_by_name (redundant with can_external_metadata) - can_read on SecurityRestApi (CSRF not needed for read-only) - can_get on OpenApi (API docs not needed) - can_get on MenuApi (menu API not needed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove checkmarks for permissions no longer in Public role: - can_get on OpenApi - can_get on MenuApi - can_read on SecurityRestApi - can_external_metadata_by_name on Datasource 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
sfirke
left a comment
There was a problem hiding this comment.
I am really pleased you're taking this on! I went through many comments related to frustrations with everyone who tried to figure this out on their own trial and error. I think this is a huge win for the project!
I shared thoughts and additional info in the comments below.
| ("can_get", "Datasource"), | ||
| ("can_external_metadata", "Datasource"), | ||
| } | ||
|
|
There was a problem hiding this comment.
I have a Public role in production. I set it up around 2022 so many versions ago. Here I compare this PR's list to the list I'm using, both ways.
An original artifact of the list I used was this gist: https://gist.github.com/byk0t/bd6e9c3839967b4ac28a8da30f468b2a its comments have a couple of useful clues.
Present here but not in my Public role
("can_read", "EmbeddedDashboard")- makes sense to add
It surprises me that my Public role works without having these:
# Datasource metadata for chart rendering
2. ("can_get", "Datasource"),
3. ("can_external_metadata", "Datasource")
Present in my Public role but not this PR
I think we might want to add:
can annotation json Superset- I would think this is needed for annotations to render on a Public-facing chart?can read Annotation- samecan filter Superset- I don't know how this is different from the filter permissions you have abovecan read ExplorePermalinkRestApi- I think this was for permalinks to charts? I was trying to embed charts in webpages when I started using Superset for public facing.
I'm not sure about these - I have them but it's not obvious to me what they do and I don't remember why I added each:
can favstar Superset- at least in Superset 1.5.0 this was needed to avoid the error message: "There was an issue fetching the favorite status of this dashboard"can get OpenApican list FilterSetscan queries Supersetcan read AdvancedDataTypecan read ExploreFormDataRestApi,can share dashboard Supersetcan slice json Supersetcan sql json Supersetcan validate sql json Supersetcan write DashboardPermalinkRestApi- maybe I had this because of Without "can write on DashboardPermalinkRestApi", a click on a anchor (tabs or header) redirect to login page #30004 which has been fixed?can write ExploreFormDataRestApican write ExplorePermalinkRestApi
Probably only a fit for my use case:
can csv Superset- maybe we note in the docs that if you want the public user to be able to download the data behind a chart, add this?
- Fix config logic: Only enable built-in Public role when explicitly set to PUBLIC_ROLE_LIKE = "Public" (not when None/unset) to avoid breaking existing deployments - Add permissions for annotations (can_read Annotation, AnnotationLayerRestApi) so charts with annotations render properly for public users - Add can_read ExplorePermalinkRestApi for chart permalink support - Update docs with DASHBOARD_RBAC interaction notes - Document that role is synced on startup (manual edits may be overwritten) - Update STANDARD_ROLES.md with new permissions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Thanks for the thorough review @sfirke! Your feedback was incredibly valuable. I've pushed updates that address your concerns: Changes Made1. Config Logic Fix (Critical)You were right to flag this! The original logic Fixed: Now the built-in Public role only activates when explicitly set to 2. Additional Permissions Added
3. Documentation UpdatesAdded important notes covering:
Permissions NOT Added (and why)
Let me know if there's anything else you'd like me to adjust! |
Annotation permissions (can_read on Annotation and AnnotationLayerRestApi) are intentionally granted to Public even though Gamma doesn't have them. This is because Annotation is in ALPHA_ONLY_VIEW_MENUS, but Public users need these permissions for charts with annotations to render properly. Also fixes STANDARD_ROLES.md to correctly show that Gamma does NOT have Annotation permissions (they are Alpha-only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Thanks for the thorough review @sfirke - all addressed! |
sfirke
left a comment
There was a problem hiding this comment.
The content of this PR
Looking sharp! I have two suggestions on the docs, one of which requires you to test something out because I'm not sure what sentence is true there.
Related documentation fixes
I looked for related documentation and it's pretty woeful. Two suggestions:
- I think this PR should update this section on the Security page about the Public role. suggesting they use Public instead of Gamma.
DASHBOARD_RBAC:DASHBOARD_RBACseems to be pretty much undocumented. The closest thing is "Manage access to Dashboards" on the "Creating your first dashboard" page, which should be moved from "Using Superset" into the "Configuration" section of the docs.
On the Networking page we say it's needed to make a dashboard public:
These are in a circular loop of docs pointer links. The link in this screenshot takes you to the Feature Flags page:
Where there's a link "(docs)" that takes you back to the meager paragraph on the "creating your first dashboard" page:
I think the fix is to make the move I suggested above, from "creating your first dashboard" into the appropriate place in the Configuration documents. Then any/all these references to DASHBOARD_RBAC can point there.
| - **Role synchronization:** The Public role permissions are synchronized on Superset startup | ||
| when `PUBLIC_ROLE_LIKE = "Public"`. Any manual permission edits to the Public role may be | ||
| overwritten during upgrades or restarts. To add custom permissions, consider creating a | ||
| separate role and granting it to users alongside the Public role. |
There was a problem hiding this comment.
I've been thinking about this and I think a better recommendation would be:
To customize the permissions assigned to the Public role, make a copy of it via the "Copy Role" option available to admins in the Superset web UI and save it under a different name. Alter it as desired, then edit your config file to point to that copied role, e.g.,
PUBLIC_ROLE_LIKE = "Public_Custom".
There was a problem hiding this comment.
Wait, about this:
The Public role permissions are synchronized on Superset startup when
PUBLIC_ROLE_LIKE = "Public".
Seems inaccurate -- are role permissions synchronized for Gamma, Alpha, etc.? I don't think this is accurate to say they're synchronized on startup when that value is set in the config. Instead either all roles are synchronized on startup (when superset init is run) or none, I would think.
| also grant access to specific datasets by editing the Public role in the Superset UI | ||
| (Menu → Security → List Roles → Public) and adding the relevant data sources. | ||
|
|
||
| - **Using with DASHBOARD_RBAC:** If you have the `DASHBOARD_RBAC` feature flag enabled, |
There was a problem hiding this comment.
I think the content of this paragraph and the preceding one are correct, but I might streamline it into one thing. Along the lines of:
"The Public role only grants UI/API permissions. You must also grant access to specific datasets necessary to view a dashboard. As is the case for other roles, this can be done in two ways:
- With DASHBOARD_RBAC feature flag set to False: <placeholder>. Grant access to specific datasets by editing the Public role in the Superset UI (Menu → Security → List Roles → Public) and adding the relevant data sources.
- With DASHBOARD_RBAC feature flag set to True: Anonymous users will only see dashboards where the "Public" role has been explicitly added as an owner in the dashboard's properties. There will be no need to grant access to specific datasets, this cascading permissions check is handled by DASHBOARD_RBAC. This provides fine-grained control over which dashboards are publicly visible."
Where it says "placeholder" above I want to add: "the Public role can see all dashboards on the dashboard list. It can load them, but won't be able to see any of the charts without access to their datasets." But I don't know if this is true! Can you test this and fill in the placeholder with a sentence about what dashboards are visible in this case?
sfirke
left a comment
There was a problem hiding this comment.
I realized I didn't understand why my current config is working the way I want it. I found a line that seems to depend on a role named "Public"? Seems relevant to this PR. Sorry to generate so much followup!
| - User profile or admin features | ||
| - Menu access to most Superset features | ||
|
|
||
| To enable anonymous access with the built-in Public role, set `PUBLIC_ROLE_LIKE` in your config: |
There was a problem hiding this comment.
I think this needs to get folded into the DASHBOARD_RBAC discussion below. I currently use the Public role with DASHBOARD_RBAC = True and I don't have PUBLIC_ROLE_LIKE in my config and I don't plan to. Instead, I just assign the Public role to dashboards I want public.
I think this section should say you set PUBLIC_ROLE_LIKE = "Public" if you're not using DASHBOARD_RBAC. If you are using DASHBOARD_RBAC and want finer controls, simply grant the Public role to the dashboards you want.
Hold on... how does this work in my current deployment where I don't have PUBLIC_ROLE_LIKE but anonymous users get it assigned anyway?? I think I traced it to this block:
superset/superset/views/utils.py
Lines 107 to 110 in fb6f3fb
If I'm correct, that's assigning a role called "Public" to anonymous users? That seems brittle, and maybe something to address here.
There was a problem hiding this comment.
I like that we can tell Superset to use a role for anonymous users, but should this be the role defined in PUBLIC_ROLE_LIKE and not hard-coded to "Public" - especially if there's now a stock role and people might want to point it to a customized other one?
|
Thanks @sfirke! We'll get this dialed in before merging, obviously! |
…ssignment - Fix hard-coded "Public" role in bootstrap_user_data to use get_public_role() which respects AUTH_ROLE_PUBLIC config - Clarify PUBLIC_ROLE_LIKE is optional (only controls permission sync during superset init) - Add consolidated DASHBOARD_RBAC documentation to security.mdx - Explain two approaches for making dashboards public (dataset-based vs dashboard-level access) - Update networking-settings.mdx with clearer public dashboard instructions - Streamline creating-your-first-dashboard.mdx to link to consolidated docs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
CodeAnt AI is running Incremental review Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
|
Thanks for the detailed review! I've pushed updates addressing all the feedback: Documentation ImprovementsClarified
Consolidated DASHBOARD_RBAC documentation:
Fixed "Role synchronization" section:
Streamlined data access explanation:
Bug FixFixed hard-coded "Public" role in
|
There was a problem hiding this comment.
Code Review Agent Run #8f0e3a
Actionable Suggestions - 1
-
superset/security/manager.py - 1
- Role Name Inconsistency · Line 1268-1268
Additional Suggestions - 1
-
docs/docs/security/security.mdx - 1
-
Doc inaccuracy on DASHBOARD_RBAC · Line 146-148The documentation claims that DASHBOARD_RBAC bypasses dataset-level checks and implicitly grants access to all charts and datasets in the dashboard. However, a GitHub issue (#31938) reports that this may not work as intended, potentially still requiring explicit dataset permissions. Consider updating to reflect this limitation or noting that users should verify the behavior.
-
Review Details
-
Files reviewed - 9 · Commit Range:
07fd30f..cc7c30e- docs/docs/configuration/networking-settings.mdx
- docs/docs/security/security.mdx
- docs/docs/using-superset/creating-your-first-dashboard.mdx
- pyproject.toml
- superset/security/manager.py
- superset/views/utils.py
- tests/integration_tests/fixtures/__init__.py
- tests/integration_tests/fixtures/public_role.py
- tests/integration_tests/security_tests.py
-
Files skipped - 1
- RESOURCES/STANDARD_ROLES.md - Reason: Filter setting
-
Tools
- Whispers (Secret Scanner) - ✔︎ Successful
- Detect-secrets (Secret Scanner) - ✔︎ Successful
- MyPy (Static Code Analysis) - ✔︎ Successful
- Astral Ruff (Static Code Analysis) - ✔︎ Successful
Bito Usage Guide
Commands
Type the following command in the pull request comment and save the comment.
-
/review- Manually triggers a full AI review. -
/pause- Pauses automatic reviews on this pull request. -
/resume- Resumes automatic reviews. -
/resolve- Marks all Bito-posted review comments as resolved. -
/abort- Cancels all in-progress reviews.
Refer to the documentation for additional commands.
Configuration
This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.
Documentation & Help
| # If not set (None), the Public role remains empty (default/legacy behavior). | ||
| public_role_like = get_conf()["PUBLIC_ROLE_LIKE"] | ||
| if public_role_like == "Public": | ||
| # Use the built-in Public role with minimal read-only permissions |
There was a problem hiding this comment.
The set_role call uses a hardcoded "Public" string, but to match the AUTH_ROLE_PUBLIC config (which defaults to "Public" but can be customized), it should use self.auth_role_public. This ensures consistency, as the copy_role in the elif branch correctly uses self.auth_role_public.
Citations
- Rule Violated: AGENTS.md:86
Code Review Run #8f0e3a
Should Bito avoid suggestions like this for future reviews? (Manage Rules)
- Yes, avoid them
…ss (apache#36548) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
SUMMARY
This PR adds a new built-in "Public" role to Superset, designed for anonymous/unauthenticated users who need to view dashboards. The Public role is more restrictive than Gamma and provides sensible defaults for public-facing dashboard deployments.
Background: In #36025, it was identified that using
PUBLIC_ROLE_LIKE = "Gamma"grants excessive permissions including write and delete capabilities that are inappropriate for public access. Rather than documenting a complex set of manual permissions, this PR creates a new built-in role with sensible, secure defaults.Key changes:
PUBLIC_ROLE_PERMISSIONSset defining minimal dashboard viewing permissions_is_public_pvm()method to determine Public role permissionssync_role_definitions()alongside Admin, Alpha, Gamma, and sql_labPUBLIC_ROLE_LIKE = "Public"to use these safe defaultsThe Public role includes:
can_read on Dashboard,can_read on Chart)can_read/write on DashboardFilterStateRestApi)can_read on DashboardPermalinkRestApi,can_read on ExplorePermalinkRestApi)can_read on EmbeddedDashboard)can_read on Annotation,can_read on AnnotationLayerRestApi)can_get,can_external_metadataon Datasource)can_read on CssTemplate)can_time_range,can_query_form_data,can_queryon Api)The Public role explicitly excludes:
all_datasource_accessorall_database_accesspermissionsImportant notes:
PUBLIC_ROLE_LIKE = "Public"is explicitly set. If unset (None), the Public role remains empty, preserving existing/legacy behavior.DASHBOARD_RBACfeature flag enabled, anonymous users only see dashboards where the "Public" role has been explicitly added as an owner.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A - This is a backend role/permission change.
TESTING INSTRUCTIONS
superset initto sync role definitionsPUBLIC_ROLE_LIKE = "Public"in config and verify anonymous users can view dashboards but cannot:ADDITIONAL INFORMATION
🤖 Generated with Claude Code