Unassign policies for expired Ultimate licenses
What does this MR do and why?
Introduces a cron worker to automatically unassign security policy configurations when an Ultimate license or plan expires. This worker identifies namespaces with expired Ultimate subscriptions (SaaS) or expired Ultimate licenses (self-managed) and schedules a dedicated worker to remove their associated policy configurations. This ensures that security policies are only active with a valid Ultimate plan.
References
This is part 2 of fixing #431229
Part 1 MR : !208917 (merged)
Database Query Plans
SELECT
gsh.*
FROM
gitlab_subscription_histories gsh
INNER JOIN
plans hosted_plan
ON hosted_plan.id = gsh.hosted_plan_id
WHERE
gsh.end_date = '2025-10-20'
AND hosted_plan.name IN ('ultimate', 'ultimate_trial', 'ultimate_trial_paid_customer');
explain: https://console.postgres.ai/gitlab/gitlab-production-main/sessions/44794/commands/137546
Screenshots or screen recordings
Before | After |
---|---|
How to set up and validate locally
- Simulate SAAS instance https://docs.gitlab.com/development/ee_features/#simulate-a-saas-instance
- Create a new test group and one project in it
- Enable
Allow use of licensed EE features
and assignUltimate
plan to the test group following the steps mentioned here - Create security policies with any security policy for the project and group
- Update the group plan to "Premium"
- Find the subscription_history and update the end_date then execute the cron worker
namespace = Namespace.find_by(path: 'your-namespace-path')
subscription_histories = namespace.gitlab_subscription_histories.with_a_ultimate_hosted_plan.first.update!(end_date: 3.days.ago.to_date)
Security::UnassignPolicyConfigurationsForExpiredLicensesCronWorker.new.perform
- Verify the security policies are unlinked
- Through UI: Update the group license to "Ultimate" and see the policies are no longer exists
- From rails console:
# should return zero
namespace = Namespace.find_by(path: 'your-namespace-path')
namespace_ids = namespace.self_and_descendants.pluck_primary_key
project_ids = namespace.all_project_ids
Security::OrchestrationPolicyConfiguration.for_namespace_and_projects(namespace_ids, project_ids).count
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 #431229
Edited by Imam Hossain