Harden Secrets Manager add-on enable mutation
What does this MR do and why?
Follow-up to !253618 (merged), which introduced the SecretsManagerEnableAddOn GraphQL mutation. This MR fixes defects flagged in review at !253618 (comment 3790514834) and !253618 (comment 3791124895), which were deferred to a follow-up, plus one additional issue found by the author.
Fixes:
-
Granular token scope.
authorize_granular_tokenonly requiredread_secrets_manager, so a read-only fine-grained token could convert a group to paid and provision it. The mutation now has a dedicated permission,enable_secrets_manager_add_on: a new raw permission (config/authz/permissions/secrets_manager_add_on/enable.yml, granted to Owner) and a new assignable permission group with agroupboundary (config/authz/permission_groups/assignable_permissions/secrets_management/secrets_manager_add_on/enable.yml). Enabling a paid add-on is a billing action, so it gets its own permission rather than reusing the enrollment or provisioning ones, as suggested in review. Fine-grained token docs were regenerated to match. -
Conversion analytics.
track_internal_event('secrets_manager_add_on_enabled')fired unconditionally after provisioning, so a failed provisioning attempt was billed but never counted, and repeat clicks over-counted. It now fires inside the same@add_on_stampedguard as the audit event, before provisioning runs. The event definition description was updated to reflect that it counts conversions once per group. -
Stale entitlement after opt-out.
NamespaceEnrollmentService#unenrollclearedadd_on_requested_atbut not the entitlement resolver cache, andEE::Ci::RegisterJobServicecaches entitlement for up to a minute, so CI jobs could still read secrets briefly after opt-out. Both opt-out paths (unenroll,destroy_enrollment) now callSecretsManagement::Entitlement::Resolver.clear_cache. -
Non-atomic enroll + stamp. If stamping
add_on_requested_atraised afterenrollhad already written the row, the rollback token never reached the caller.enroll_with_add_on_intentnow compensates by reverting the enroll write before re-raising. -
Authorization ability. The mutation authorized
admin_group, mirroringSecretsManagerStartTrial. It now authorizes the sameenable_secrets_manager_add_onpermission the granular directive uses, so the user-level ability and the token scope say the same thing. Same Owner-only floor, butGroupPolicyprevents it unlessNamespaceEnrollment.enrollment_allowed?(SaaS, licence, and thesecrets_manager_namespace_enrollmentflag), so that gating applies at authorization instead of failing later inside the service, and theGitlab/Authz/PermissionCheckdisable is gone.provision_secrets_managerstays an explicit check right before provisioning, because the policy denies it while the group is stilltrial_eligible. One visible consequence: a subgroup path now gets the standard not-available error at authorization instead of the "top-level groups only" argument error, matchingNamespaceSecretsManagerEnroll. Answers !253618 (comment 3791124895).
Also included: the GraphQL permissions docs generator (lib/tasks/gitlab/permissions/graphql/docs_task.rb) now dedupes permission groups, so a directive listing multiple raw permissions from the same group no longer emits a self-referential "Also requires" footnote.
Left for a separate MR, tracked in the issue: SecretsManagerStartTrial has the same read-permission and admin_group problems and will get a sibling start_secrets_manager_trial permission.
References
- Closes https://gitlab.com/gitlab-org/gitlab/-/issues/627810
- Related to https://gitlab.com/gitlab-org/gitlab/-/work_items/612843
- Original MR: !253618 (merged)
- Review comments: !253618 (comment 3790514834), !253618 (comment 3791124895)
Screenshots or screen recordings
Backend-only change, no UI impact.
How to set up and validate locally
- Simulate SaaS and enable the flag: set
GITLAB_SIMULATE_SAAS=1in the environment, then in a Rails console runFeature.enable(:secrets_manager_paid_experience). - Run the permission definition and docs checks:
bundle exec rake gitlab:permissions:validate. All six checks should report valid / up-to-date. - Run the specs:
bundle exec rspec ee/spec/graphql/mutations/secrets_management/enable_add_on_spec.rb ee/spec/requests/api/graphql/mutations/secrets_management/enable_add_on_spec.rb ee/spec/services/secrets_management/namespace_enrollment_service_spec.rb spec/tasks/gitlab/permissions/graphql/docs_task_spec.rb - To see fix 1 by hand: create a fine-grained personal access token with only the
Secrets Manager: Readpermission on a top-level group and callsecretsManagerEnableAddOnwith it; it must be denied. A token withSecrets Manager Add-on: Enableon the same group is accepted (the token owner still needs to be a group Owner).
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.