As we complete &5510 (closed), we are introducing the concept of a policy scope. Existing policies may currently be enforced against a set of projects based entirely on the way they are linked.
In the future, we will add the scope check, which takes effect after any links have been established. This allows users to suppress policies in an SPP from being enforced on all linked repos, so the desired policies are granularly enforced.
This issue will confirm and validate we appropriately handle this for all existing use cases:
SaaS instance with a single policy enforced against multiple-subgroups
Self-managed instance with a single policy enforced against multiple top level groups
# frozen_string_literal: truemoduleTypesmoduleSecurityOrchestration# rubocop: disable Graphql/AuthorizeTypesclassPolicyScopeType<BaseObject# rubocop: enable Graphql/AuthorizeTypesgraphql_name'PolicyScope'authorize[]field:compliance_frameworks,[::Types::ComplianceManagement::ComplianceFrameworkType],null: false,description: 'Compliance Frameworks linked to the policy.'field:including_projects,[::Types::ProjectType],null: false,description: 'Projects to which the policy should be applied to.'field:excluding_projects,[::Types::ProjectType],null: false,description: 'Projects to which the policy should not be applied to.'endendend
For existing policies by default and on the UI we want this to be scoped to all projects in this group to not introduce any breaking change. What I've meant in this case is that we will not change or migrate any existing YAML files.
If we change UI, how came we don't change the Yaml? Shouldn't them be the same? And shall we move this to a new issue? I am afraid in the future we might lose the discuss since this is not directly related.
@cam.x Separated the discussion out from #427221 (comment 1659233021). I was considering further as well how all projects in this group may suffice for SaaS, but this seems like we'd exclude projects from other groups in the case of self-managed. If we immediately conclude nothing is needed here, we can close this issue, but I thought it worth opening and validating it further.
I'm not sure I fully follow the question regarding changing the UI/YAML. That may be worth capturing and making sure we are all aligned. @alan What exactly is the behavior w/r/t the existing YAML of a policy when we introduce the new policy option
@g.hickman, there will be no change as existing policies will be without policy scope defined, which means they will be applied on all projects in this group.
In A, once we release the feature, no scope will be applied, no change to existing policies. All policies in an SPP will be enforced against all projects linked to the SPP. I would assume the same case for self-managed users who have linked across groups to the SPP containing this policy.
In B, this will not happen post release unless a customer explicitly updates their policy to add the scope. Once they do, we'd check for any groups/subgroups/projects that are linking, then for each policy check the listed compliance frameworks and projects before enforcing the policy.
Correct?
which means they will be applied on all projects in this group
This portion of your statement I wasn't confident in or perhaps properly undertanding. We may not want to limit enforcement within a single group unless the customer defines it that way. Today, policies may be enforced across groups in self-managed instances (granted it seems they may separately need another admin setting enabled to support this?).
In A, once we release the feature, no scope will be applied, no change to existing policies. All policies in an SPP will be enforced against all projects linked to the SPP. I would assume the same case for self-managed users who have linked across groups to the SPP containing this policy.
In B, this will not happen post release unless a customer explicitly updates their policy to add the scope. Once they do, we'd check for any groups/subgroups/projects that are linking, then for each policy check the listed compliance frameworks and projects before enforcing the policy.
Exactly. Customers will probably not set that complicated scope, but it is technically possible. In this case, the policy will be enforced only on projects (12345 and 23456) with compliance frameworks (12345 or 23456).
This portion of your statement I wasn't confident in or perhaps properly undertanding. We may not want to limit enforcement within a single group unless the customer defines it that way.
Ah, I see, I was referring to the option we will show on the frontend. What I wanted to ensure is that when policy scope is not applied the policy will be applied in the same manner as it is currently. Nothing will be changed.
Customers will probably not set that complicated scope
@alan Agreed , that was a quick example I pulled from an issue to get the syntax right, so not really a "simple" example.
Ah, I see, I was referring to the option we will show on the frontend. What I wanted to ensure is that when policy scope is not applied the policy will be applied in the same manner as it is currently. Nothing will be changed.
I see what you mean, ok. I'm glad we discussed. I'm wondering if we should approach frontend differently in this case. Maybe we need a "not set" option?
I see what you mean, ok. I'm glad we discussed it. I'm wondering if we should approach the frontend differently in this case. Maybe we need a "not set" option?
@g.hickman@alan This only happens in the case that, the user uses YAML mode only, which means directly adding a policy in Security Policy Project, and this Security Policy Project is not linked to any project or group. Correct? If yes, think those policies should be Disabled because they are not in use anyway. If we have an enabled policy and the scope is Not set it is the same as Disable, if we introduce not set, we are creating two ways for the user to disable a policy, which is unnecessary.
What we are missing is: what to show when the policy is configured at project-level? Should the dropdown be different on project-level?
@alan If I don't remember wrong, we don't have scope for project-level UI. What we can do to make it clear is a read-only area like this:
I just want to make a note: our goal is to hide SSP in the future, the mental model we want to encourage users to use now and future is: that if they want to manage policy for a group, they go to the group, not linked SPP; if they want to manage policy for project, they go to the project, not the linked SPP. I think a lot of complex cognition load regarding permission and scope will be introduced if we encourage the user to go to SPP to manage their policy and then go to different projects and groups to link(It is not the workflow we encourage).
This only happens in the case that, the user uses YAML mode only, which means directly adding a policy in Security Policy Project, and this Security Policy Project is not linked to any project or group. Correct? If yes, think those policies should be Disabled because they are not in use anyway. If we have an enabled policy and the scope is Not set it is the same as Disable, if we introduce not set, we are creating two ways for the user to disable a policy, which is unnecessary.
In A, once we release the feature, no scope will be applied, no change to existing policies. All policies in an SPP will be enforced against all projects linked to the SPP. I would assume the same case for self-managed users who have linked across groups to the SPP containing this policy.
@g.hickman, correct!
Ok, I'll take one last stab at this . It is possible I'm thinking of a scenario that will not occur and that it is only my confusion.
Based on Alan's agreement regarding scenario A, we may have this policy:
This is how it would appear today, and after we introduce the concept of a policy scope, the yaml would stay the same as you see above still. No change to the policy at all. Only when they go to the policy editor would they need to change it. I'm not talking about enabled/disabled in this case.
But if the UI now shows the new option of scope, with the option "All projects in this group", it would be inaccurate, as the policy yaml would still be unchanged and would have no scope yet.
So it may just be a simple UI requirement to have the default dropdown have an option, such as "Select", "Unset", "No scope", or similar. Essentially a null or empty selection that means do not populate the yaml with any policy scope. As this will be the state of all policies until users choose to add a scope.
@cam.x I think we all agree we have a clear problem statement to solve for. I think we still all need the time to sync and discuss and ensure alignment on the solution. I'd like for us to keep an open mind until we have an opportunity to do this. Let's talk some more about this in the next sync and then plan a sync discussion on the topic. WDYT?
But if the UI now shows the new option of scope, with the option "All projects in this group", it would be inaccurate, as the policy yaml would still be unchanged and would have no scope yet.
So it may just be a simple UI requirement to have the default dropdown have an option, such as "Select", "Unset", "No scope", or similar. Essentially a null or empty selection that means do not populate the yaml with any policy scope. As this will be the state of all policies until users choose to add a scope.
Do you agree with this, do you think we need another UI dropdown option here?
@g.hickman, I believe we do not need another UI dropdown option. Even though we do not show the current Policy Scope on the UI:
when the policy is configured on the group level, the default scope for it is All projects in this group,
when the policy is configured on the project level, the default scope is Apply this policy to this project.
The fact that this is not reflected in the policy YAML does not change anything. In my opinion, when policy_scope is not applied in the YAML, we apply this policy to all projects in the group. Policy UI Editor should set policy_scope only when the user changes the All projects in this group option to something else OR adds an exception.
@alan I'm starting to see your intent here, thanks for elaborating.
when the policy is configured on the group level, the default scope for it is All projects in this group,
when the policy is configured on the project level, the default scope is Apply this policy to this project.
I think this is accurate, assuming other groups/subgroups/projects are not being linked to the security policy project. If you are linking across those boundaries, which is the current recommended approach, especially for large organizations, I'm not sure this applies exactly.
For example, with a structure such as this:
Security Group
Security Policy Management (this is repo with the policy editor)
If Subgroup A and Subgroup B are linked to Security Policy Management - security policy project, for a policy configured in the SPP, neither "All projects in this group" or "All projects in this project" would be true.
Maybe the default is technically "All groups, subgroups, and projects linked to the security policy project containing this policy".
I'll add this to our 1:1 agenda tomorrow as it's a good topic to align on. You raise good points and appreciate the discussion
To help us process, I try to describe the scenarios in a user flow:
For existing policies:
Case
Current settings
After we intro scope: In UI
After we intro scope: In Yaml
Case 1
The user has a security policy on the project level (Technically SPP has only 1 linked project)
Show a text filed, nothing changed
? Do we have a code Scope: this project?
Case 2
The user has a security policy on the group level, which is applied to all projects in the group (Technically SPP has only 1 linked group)
It shows for the user in the scope area All projects in the group as unsaved.
If user open the UI, we show the YAML as draft as well. If the user directly opens the file, we don't do anything
Case 3
The user has a security policy in an SPP, the SPP is linked to several sub-groups (Technically SPP has more than one linked projects/subgroups)
It shows for the user in the scope area Specific projects with the project linked in the sub-group as unsaved.
If the user opens the UI, we show the YAML as a draft as well. If the user directly opens the file, we don't do anything
Case 4 (Self-managed only)
The user has a security policy in a SPP and the SPP has been linked to several top-level groups (Technically SPP has more than one linked groups)
Tell the user there needs to be a manual update
Nothing, until the user updates it manually
When a user creates a new policy:
Case 1: for SaaS users, we pull compliance frameworks within the same group. User doesn't need to link policy project to subgroups, if they choose a compliance framework-A which is applied to a subgroup-B which is not linked with SPP, we automatically link it for them. We don't require users to manually link a SPP and then change the scope.
Case 2: for self-managed users, we pull compliance frameworks of the groups to which the user has access. if they choose a compliance framework-A which is applied to a Group-B which is not linked with SPP, we automatically link it for them. We don't require users to manually link a SPP and then change the scope.
@cam.x Noting some of the key changes or points from our discussion this morning:
Implicit linking of policies to compliance framework labelled projects isn’t something we’ve discussed, but may make things easier. Users with rights to add label will have already had the right to link policies.
Scoping of policies will allow users to opt out of the security policy projects, so this could be one approach.
If other groups, subgroups, or projects link to a security policy project created at the group level, we would need to update the UI to support scoping.
If intent is to create policies just for your project (e.g. as an EM), we won’t show the scope option and it keeps it simpler.
If intent is to create policies just for your single group/subgroup, we provide a UI that is intuitive for them.
I think there may be some refinements based on our discussion and we can ensure to surface this in the issue.
My takeaway is that we do have some actions here that could make it more intuitive.
As I go back through the designs, I'm less sure about the "New feature" announcements and update aspects. I feel like the UI should be intuitive enough without having to notify users and having all of these extra elements and popups
What we discussed this morning without all of that seemed to solve the challenges well. WDYT?
@g.hickman I think this summarizes well what we discussed.
What we discussed this morning without all of that seemed to solve the challenges well. WDYT?
I think users can manage themselves with documentation without the UI update I added in the previous comment.
However, one benefit of having it is that we tell users why we update the UI, but not YAML, because they need to create an MR and merge it themselves and we are guiding them. To the point of having better user experiences, I think adding this last bit is worth the effort.
Maybe the default is technically "All groups, subgroups, and projects linked to the security policy project containing this policy".
@g.hickman, I agree this describes it better. I now understand your concerns, thank you for explaining it!
Based on these discussions it looks like we are missing some functionalities:
being able to return scope for single policy from GraphQL API, we would need to add policyScope to both scanExecutionPolicies and scanResultPolicies in the GraphQL API that will return precise list of projects/compliance frameworks (FYI @sashi_kumar),
database changes to keep this information efficiently,
UI to show that information on Policies list,
policy_scope setting in YAML mode that would allow us to differentiate policies that are using default scope, perhaps policy_scope: default.
I'm thinking how we can iterate on that to ensure we can release this feature. Perhaps we could do something as @cam.x explained in #432513 (comment 1681737711), but simplified. So based on policy_scope value in the YAML, we could (instead of listing specific projects) list some information about current scope based on the context where we display that list.
I'm thinking how we can iterate on that to ensure we can release this feature.
I'm happy to break this down into iterations. I think something like policy_scope: default could work and it could align with "All groups, subgroups, and projects linked to the security policy project containing this policy" (or something simpler that means this) in the UI. I don't know if we need to list the specific projects in the existing policies but only take that on in any newly created or updated policies when the scope is specifically defined by the user.
I think that is at least the bare minimum MVC.
If we can fit it in, we can add the ability to swap the UI to add the scope selection only when a group/subgroup is linked, so users creating policies only for the project are not guided into this flow. But IYKYK (if you know you know) -- call this MVC+
We can then discuss the other ideas here and how to iterate on it.
I think with policy linking as part of our Experiment (alongside custom CI yaml and behind the same experiment toggle) we can test, get feedback here as well, and then have the right to break things and iterate, while still delivering.
I'm happy to break this down into iterations. I think something like policy_scope: default could work and it could align with "All groups, subgroups, and projects linked to the security policy project containing this policy" (or something simpler that means this) in the UI. I don't know if we need to list the specific projects in the existing policies but only take that on in any newly created or updated policies when the scope is specifically defined by the user.
@g.hickman@alan I like the default mode as well, I always try to align Yaml with UI, if the yaml is set to policy_scope: default, we probably need to have UI like this below.
policy_scope setting in YAML mode that would allow us to differentiate policies that are using default scope, perhaps policy_scope: default
@alan Thanks for the summary! Instead, we can add a field default: true/false within policy_scope so that it stays consistent with the current schema (as policy_scope is an object). I've updated the backend implementation to update the graphql API.
@arfedoro Let me know if the backend changes would be enough for frontend changes
Doest it make sense to have default false? Having complieance_frameworks in policy_scope would already mean not default state? correct?
@arfedoro, great questions and I agree with you: default: false makes no sense as with default: false we would need to enforce settings compliance_frameworks or projects properties. So we can assume that the default state would be either no policy_scope at all or policy_scopw with empty properties, like:
policy_scope:compliance_frameworks:[]
Or will some migration be run in db, and all policies would get by default:
We cannot perform any background migration to update files in the repository, so this would not be an option. We need to support existing policies without any type of migration.
@alan@arfedoro If I'm following the discussion here correctly, I think there's a small nuance we need to consider here.
If a customer is creating their central policies in a project-level SPP and they have linked multiple groups, subgroups, or project so this project-level SPP, the implementation plan here forced the user to reconfigure their policies to manage them at a group/subgroup level.
I don't believe this should be necessary for the customer to have to "start over" necessarily. I believe we had discussed at one point the following (I can try to trace it back but I think it's in this discussion somewhere):
If the project-level SPP has more than a project linked to it, give them the option to scope it the same as a group/subgroup level SPP.
If the only link is to the one project, do not make it apparent to the user this is possible. As show in the design here, in this case, it would state "Apply this policy to current project" only.
This would incentivize new users to now take advantage of using the group/subgroup level to manage policies instead of using a project-level SPP to workaround previous limitations. However, for customers who were required to use the project-level SPP, they can apply scopes and use them without having to reconfigure.
If a customer is creating their central policies in a project-level SPP and they have linked multiple groups, subgroups, or project so this project-level SPP, the implementation plan here forced the user to reconfigure their policies to manage them at a group/subgroup level.
I don't believe this should be necessary for the customer to have to "start over" necessarily. I believe we had discussed at one point the following (I can try to trace it back but I think it's in this discussion somewhere):
If the project-level SPP has more than a project linked to it, give them the option to scope it the same as a group/subgroup level SPP.
If the only link is to the one project, do not make it apparent to the user this is possible. As show in the design here, in this case, it would state "Apply this policy to current project" only.
Are there any concerns/challenges in doing this?
Sounds perfect, the only missing piece is that we do not have information if given SPP is already linked as single project-level SPP or is linked on multiple level. Although, this should be quite simple to implement. My idea here would be to return additional information in orchestration_policy_data helper indicating that given policy is linked once or multiple times. When it is linked multiple times then we would give users the option to scope it the same as a group/subgroup level SPP.
Now when user create/edit SPP project policy, we make a query to check how many linked projects/namespaces SPP project has.
My question is what if query fails, should we show user an error message with retry option, or we would just show fallback UI which can be either regular UI with compliance frameworks selector or this default text Apply this policy to current project?
@alan, by the way you mentioned in this comment, that orchestration_policy_data helper should be used for that, is there an specific reason why you decided to use graphql?
@arfedoro, it will be more universal to use graphql as we've seen similar request in the past to be able to list linked namespaces/projects to given Security Policy Project. In case using helper will be simpler for you, we can also add this quite quickly based on my recently created MR:
I am totally ok with using grapqhl. The main difference for UI is:
In case of graphql, we make a query after we open policy editor, in this case I need to show some loading state on project level (since we have difference in UI only on project level) , and error handling if it fails, what I asked in comment above, @cam.x could you help me with that, how should it look?
In case with helper, when we open a page, data about linked projects/namespaces is already there and based on it I can show either text or regular UI with compliance frameworks selector
Thank you for the snippet @alan, I will test both approaches, but I lean towards helper, because in would be consistent with current approach we have and won't require extra effort from @cam.x
In case of graphql, we make a query after we open policy editor, in this case I need to show some loading state on project level (since we have difference in UI only on project level) , and error handling if it fails, what I asked in comment above, @cam.x could you help me with that, how should it look?
@arfedoro Thank you for ping. If I understand correctly, it is like the graphql is not responding to our request, so the following error message is correct. And the user can refresh the page, so we might get the response back.
@arfedoro Ah, as you've suggested, let's continue with @cam.x approach, as I realized that my idea will not work when creating policy for newly created policy for the project.
@arfedoro I'm catching up and may have missed this one -- it looks like it's sorted out, but let me know if there are any remaining open questions for me!
All SUS-impacting issues need to have a proper severity label set.
Please add a severity label, remove the automation:ux-missing-labels label, and then reply to this comment briefly explaining your reasoning for providing this severity.
If you are not the DRI for this area and would like help determining the best severity, please @ the appropriate person for assistance.
This issue has been sent back to workflowrefinement because it's missing the weight. Please add a
weight and then send it back to workflowready for development. If indeed this issue does not need a
weight, then it must be either (labelled as a spike or typebug), or (unlabelled as frontend and backend).