Policy not linked back to the project after enabling it

Summary

A Security::Policy is linked to a project when it's enabled and applicable based on the policy_scope.

If a policy is disabled and enabled again, the link to the project is lost.

A workaround would probably involve re-linking of the SPP to trigger the full policy sync.

Steps to reproduce

  1. Create a project
  2. Create a policy
  3. Verify that project.security_policies lists the policy
  4. Update it to status: disabled
  5. Verify that it's not included in the project.security_policies
  6. Update it back to status: enabled
  7. project.security_policies still returns [], although it should list the policy.

Example Project

What is the current bug behavior?

Policy link to the project is lost.

What is the expected correct behavior?

Policy link to the project is restored when the policy gets enabled.

Relevant logs and/or screenshots

Output of checks

Results of GitLab environment info

Expand for output related to GitLab environment info

(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:env:info`)

(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)

Results of GitLab application Check

Expand for output related to the GitLab application check

(For installations with omnibus-gitlab package run and paste the output of: sudo gitlab-rake gitlab:check SANITIZE=true)

(For installations from source run and paste the output of: sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)

(we will only investigate if the tests are passing)

Possible fixes

diff --git a/ee/app/services/security/security_orchestration_policies/sync_project_service.rb b/ee/app/services/security/security_orchestration_policies/sync_project_service.rb
index ff56fe3e96c5..e131cf693356 100644
--- a/ee/app/services/security/security_orchestration_policies/sync_project_service.rb
+++ b/ee/app/services/security/security_orchestration_policies/sync_project_service.rb
@@ -9,9 +9,13 @@ def initialize(security_policy:, project:, policy_changes:)
       end
 
       def execute
-        return sync_policy_changes if policy_diff.any_changes?
-
-        link_policy
+        if policy_diff.any_changes?
+          # Existing policy has been changed.
+          sync_policy_changes
+        else
+          # Policy has just been created, link it.
+          link_policy
+        end
       end
 
       private
@@ -27,6 +31,8 @@ def policy_diff
 
       def sync_policy_changes
         return unlink_policy if should_unlink_policy?
+
+        link_policy if should_link_policy?
         return unless security_policy.type_approval_policy?
 
         sync_project_approval_policy_rules_service.sync_policy_diff(policy_diff)
@@ -36,13 +42,25 @@ def should_unlink_policy?
         policy_disabled? || policy_unscoped?
       end
 
+      def should_link_policy?
+        policy_enabled? || policy_scoped?
+      end
+
       def policy_disabled?
         policy_diff.status_changed? && !security_policy.enabled?
       end
 
+      def policy_enabled?
+        policy_diff.status_changed? && security_policy.enabled?
+      end
+
       def policy_unscoped?
         policy_diff.scope_changed? && !security_policy.scope_applicable?(project)
       end
+
+      def policy_scoped?
+        policy_diff.scope_changed? && security_policy.scope_applicable?(project)
+      end
     end
   end
 end
Edited by Sashi Kumar Kumaresan