Implement Support for Project Policies
Current Behavior:
As of v4.6.x, the policy system in Dependency-Track is based around components only. There is no support for policies that operate at the project-level.
Proposed Behavior:
Expand the policy "engine" to implement support for policies that operate on projects rather than components. A couple of use cases:
- policy that alerts when project has not had a BOM uploaded for XXX time. See #2052
- policy that allows association between licenses in a project. ie, License X might be acceptable on its' own. Licence Y might be acceptable on its' own. But X and Y must not be allowed in the same project because X and Y are mutually incompatible. My employer's legal department is quite insistent about this!
Another use case: a policy that alerts when the total number of vulnerabilities of type x is greater than y (with y > 1) - for example 2 medium vulnerabilities are fine but 3 are bad.
I am working on a PoC for https://github.com/DependencyTrack/dependency-track/issues/2673 at the moment, and in doing so I'm also looking at supporting project policies.
With CEL, the policies mentioned in this issue would be solvable like this:
policy that alerts when project has not had a BOM uploaded for XXX time
e.g. No BOM uploaded in a week:
(now() - project.last_bom_import) >= duration("1w")
policy that allows association between licenses in a project. ie, License X might be acceptable on its' own. Licence Y might be acceptable on its' own. But X and Y must not be allowed in the same project because X and Y are mutually incompatible.
components.map(c, c.license).exists(l, l.name == "License X")
&& components.map(c, c.license).exists(l, l.name == "License Y")
a policy that alerts when the total number of vulnerabilities of type x is greater than y (with y > 1) - for example 2 medium vulnerabilities are fine but 3 are bad.
components.map(c, c.vulns).filter(v, v.severity in ["MEDIUM", "HIGH", "CRITICAL"]).size() > 2
Note
For completeness' sake, I would expect the CEL feature to only make it intomasterif there's accompanying docs to go along with it, with uses cases like these explained, and sample CEL expressions provided.
The flexibility required to fulfill these policies is (IMO) not possible without an expression language. As such, I'd rank #2673 as a precondition for this issue.
How I'd envision project policies to work alongside the existing component policies:
- Policies will have a scope qualifier, which can be either Project or Component
- Available conditions depend on which scope was selected
- Some conditions may work in both scopes, but some will only work in one of the two
- In the context of CEL, the scope will dictate the available context, e.g.
- In Component scope, the context will include:
component: Object holding info about the componentproject: Object holding info about the projectvulns: List of objects holding info about the vulnerabilities
- In Project scope, the context will include:
components: List of objects holding info about the components, and vulnerabilities affecting those components (components[i].vulns)project: Object holding info about the project
- In Component scope, the context will include:
- When upgrading from an earlier DT version, all existing policies will be migrated to the Component scope
- All existing policy conditions will continue to work, but new conditions can make use of CEL
- Policy violations can be raised against projects (for Project scope), or individual components (for Component scope)
Does this sound alright? Anything else we should investigate or keep in mind? Any suggestions or concerns?