Handle insufficient privilege in vacuum activity query
What
Fixes the Admin area Database Diagnostics page
(/admin/database_diagnostics), where the "Database information"
panel showed only the generic banner "Failed to gather information
for database: main" on gitlab.com.
Introduced by
!239928 (merged), which
added the vacuum activity query with the pg_stat_activity join.
Why
The application database role on gitlab.com is not a superuser and
is not a member of pg_monitor. The in-progress vacuum query in
lib/gitlab/database/database_information.rb joins
pg_stat_activity to read the vacuum type, anti-wraparound status,
and running time. Postgres raises PG::InsufficientPrivilege for
that join under this role. The panel's single catch-all rescue
turned that error into a failure for the entire database payload,
so no information was shown at all, not even the parts the role can
read.
How
The vacuum query now catches PG::InsufficientPrivilege errors
raised as ActiveRecord::StatementInvalid and retries without the
pg_stat_activity join. The progress data from
pg_stat_progress_vacuum, which the role can read, is still
returned. The three activity-derived fields (type, running time,
anti-wraparound status) are set to null in that case.
The payload now includes a vacuum_activity_available boolean. When
it is false, the Vacuum information panel shows a warning banner
explaining that the role cannot read pg_stat_activity and that
granting pg_monitor membership restores the full details. Progress
metrics are still shown in that state.
Any other error is unaffected and still surfaces as before.
No database migration and no feature flag are needed.
How to test locally
Automated specs
bundle exec rspec spec/lib/gitlab/database/database_information_spec.rb
yarn jest spec/frontend/admin/database_diagnostics/components/db_vacuum_section_spec.js \
spec/frontend/admin/database_diagnostics/components/vacuum_information_app_spec.jsHappy path (UI)
Visit /admin/database_diagnostics as an admin. The "Database
information" and "Vacuum information" panels should render. To see a
live row, start a manual vacuum in another session first, for
example VACUUM (VERBOSE) some_large_table;.
Reproducing the warning banner (UI)
GDK's database role is a superuser, which bypasses table ACLs, so the error only appears when the app runs as a non-superuser role that is denied the view. This is why it surfaced on gitlab.com and not in a default GDK.
Do not grant the new role membership in the owner role. A member
inherits the owner's privileges, including its access to
pg_stat_activity, so the restriction would not take effect. Grant
the app privileges explicitly instead.
-
Create the role and deny the view (as the GDK superuser, via
gdk psql -d gitlabhq_development). Adjust the schema list if your instance has other schemas holding tables:CREATE ROLE diag_limited LOGIN PASSWORD 'diag' NOSUPERUSER; GRANT CONNECT, TEMPORARY ON DATABASE gitlabhq_development TO diag_limited; GRANT USAGE ON SCHEMA public, gitlab_partitions_dynamic, gitlab_partitions_static TO diag_limited; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public, gitlab_partitions_dynamic, gitlab_partitions_static TO diag_limited; GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public, gitlab_partitions_dynamic, gitlab_partitions_static TO diag_limited; REVOKE SELECT ON pg_catalog.pg_stat_activity FROM PUBLIC; -
Confirm the role is restricted but can still run the other queries:
SELECT has_table_privilege('diag_limited', 'pg_catalog.pg_stat_activity', 'SELECT'); -- f SET ROLE diag_limited; SELECT count(*) FROM pg_stat_progress_vacuum; -- ok SELECT count(*) FROM pg_stat_progress_vacuum v LEFT JOIN pg_stat_activity a ON a.pid = v.pid; -- ERROR: permission denied for view pg_stat_activity RESET ROLE; -
Point the
mainconnection at the role inconfig/database.yml, underdevelopment.main, add:username: diag_limited password: diagOnly
mainneeds this;ciandseccan stay on the default role. The default GDKpg_hba.conftrusts local socket connections, so the password may be ignored. -
Run
gdk restart rails, then visit/admin/database_diagnostics. The Vacuum information panel shows the warning banner. With no vacuum running you also see "No vacuum operations are currently running"; the Database information panel renders normally. -
Restore state when done: revert the
config/database.ymlchange, then:GRANT SELECT ON pg_catalog.pg_stat_activity TO PUBLIC; DROP OWNED BY diag_limited; DROP ROLE diag_limited;Run
gdk restart railsagain to reconnect as the original role.
Testing
- Added backend specs in
spec/lib/gitlab/database/database_information_spec.rbcovering the insufficient privilege retry path. - Added frontend specs in
db_vacuum_section_spec.jsandvacuum_information_app_spec.jscovering the warning banner. - RuboCop and ESLint are clean.

