Add instance_ssh_certificates table, model, and feature flag
Why
Lay the foundation for instance-level SSH certificate authorities. GitLab Dedicated admins currently must edit config.yml on the filesystem to trust an SSH CA; this table lets that configuration move into the database instead.
What
Add instance_ssh_certificates table, model, and feature flag
Reviewer note
One deliberate deviations from the related issue recommendation:
- No sharding key exemption entry. The table uses gitlab_schema: gitlab_main_cell_setting, which already sets require_sharding_key: false. Adding an exemption would fail spec/lib/gitlab/organizations/sharding_key_spec.rb:406, and that same spec forbids a sharding key on a cell-local table in the first place.
Changelog: added
Database migration
Click to expand
VERSION=20260819124706 bundle exec rails db:migrate:down:main
main: == [advisory_lock_connection] object_id: 162860, pg_backend_pid: 50508
main: == 20260819124706 CreateInstanceSshCertificates: reverting ====================
main: -- drop_table(:instance_ssh_certificates)
main: -> 0.0803s
main: == 20260819124706 CreateInstanceSshCertificates: reverted (0.0903s) ===========
main: == [advisory_lock_connection] object_id: 162860, pg_backend_pid: 50508
Pro tip: try out scripts/database/migrate.rb for better migration management.
VERSION=20260819124706 bundle exec rails db:migrate:main
main: == [advisory_lock_connection] object_id: 163280, pg_backend_pid: 51236
main: == 20260819124706 CreateInstanceSshCertificates: migrating ====================
main: -- create_table(:instance_ssh_certificates)
main: -- quote_column_name(:title)
main: -> 0.0000s
main: -- quote_column_name(:key)
main: -> 0.0000s
main: -> 0.0538s
main: == 20260819124706 CreateInstanceSshCertificates: migrated (0.0611s) ===========
main: == [advisory_lock_connection] object_id: 163280, pg_backend_pid: 51236
Pro tip: try out scripts/database/migrate.rb for better migration management.Database review
InstanceSshCertificate.for_fingerprint scope
scope :for_fingerprint, ->(fingerprint) { where(fingerprint: fingerprint) }fingerprint is a sha256_attribute, so the supplied value is encoded to
bytea before the query. There is no pagination or additional chaining;
fingerprint carries a unique index, so the scope returns at most one row.
Full query (from InstanceSshCertificate.for_fingerprint(...).to_sql):
SELECT "instance_ssh_certificates".*
FROM "instance_ssh_certificates"
WHERE "instance_ssh_certificates"."fingerprint" = $1;Execution plan (EXPLAIN (ANALYZE, BUFFERS), backed by the unique index
index_instance_ssh_certificates_on_fingerprint):
Index Scan using index_instance_ssh_certificates_on_fingerprint on instance_ssh_certificates (cost=0.15..2.17 rows=1 width=120) (actual time=0.001..0.001 rows=0 loops=1)
Index Cond: (fingerprint = '\xe3b0c...'::bytea)
Buffers: shared hit=2
Planning:
Buffers: shared hit=95
Planning Time: 0.345 ms
Execution Time: 0.010 msThe query is a single-row index lookup on the unique fingerprint index
(estimated rows=1), so it needs no pagination or limit. The table is empty
locally, hence actual rows=0, but the plan is representative: the unique
constraint guarantees at most one match regardless of table size.
References
Screenshots or screen recordings
| Before | After |
|---|---|
How to set up and validate locally
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #611272 (closed)