Skip to content

Commit

Permalink
Add license condition test (#332)
Browse files Browse the repository at this point in the history
* Add version cel policy script builder

Signed-off-by: vithikashukla <[email protected]>

* add version support for coordinates cel policy

Signed-off-by: vithikashukla <[email protected]>

* Added unit test for version policy script builder

Signed-off-by: vithikashukla <[email protected]>

* added coordninates condition test

Signed-off-by: vithikashukla <[email protected]>

* added coordinates condition test

Signed-off-by: vithikashukla <[email protected]>

* added more conditions to test

Signed-off-by: vithikashukla <[email protected]>

* Added license condition test

Signed-off-by: vithikashukla <[email protected]>

* Update src/main/java/org/dependencytrack/policy/cel/CelPolicyEngine.java

Co-authored-by: Niklas <[email protected]>
Signed-off-by: VithikaS <[email protected]>

* Added license group condition test

Signed-off-by: vithikashukla <[email protected]>

* updated comment

Signed-off-by: vithikashukla <[email protected]>

---------

Signed-off-by: vithikashukla <[email protected]>
Signed-off-by: VithikaS <[email protected]>
Co-authored-by: vithikashukla <[email protected]>
Co-authored-by: Niklas <[email protected]>
  • Loading branch information
3 people authored Sep 26, 2023
1 parent e2082bf commit d19301c
Show file tree
Hide file tree
Showing 4 changed files with 342 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public void evaluateProject(final UUID uuid) {

// Preload licenses for the entire project, as chances are high that they will be used by multiple components.
final Map<Long, org.hyades.proto.policy.v1.License> licenseById;
if (requirements.containsKey(TYPE_LICENSE)) {
if (requirements.containsKey(TYPE_LICENSE) || (requirements.containsKey(TYPE_COMPONENT) && requirements.get(TYPE_COMPONENT).contains("resolved_license"))) {
licenseById = celQm.fetchAllLicenses(project.getId(), requirements.get(TYPE_LICENSE), requirements.get(TYPE_LICENSE_GROUP)).stream()
.collect(Collectors.toMap(
projection -> projection.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,74 @@
public class CoordinatesConditionTest extends AbstractPostgresEnabledTest {
private Object[] parameters() {
return new Object[]{
// MATCHES regex
new Object[]{PolicyCondition.Operator.MATCHES, "{\"group\": \"acme*\",\"name\": \"acme*\",\"version\": \">=v1.2*\"}", "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", true},
//Exact match
new Object[]{PolicyCondition.Operator.MATCHES, "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", true},
//Group does not match
new Object[]{PolicyCondition.Operator.MATCHES, "{\"group\": \"org.hippo\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", false},
//MATCHES group regex
new Object[]{PolicyCondition.Operator.MATCHES, "{'group': 'acme*','name': 'acme*','version': '>=v1.2*'}", "{'group': 'acme-app','name': 'acme-lib','version': 'v1.2.3'}", true},
//Exact matches
new Object[]{PolicyCondition.Operator.MATCHES, "{'group': 'acme-app','name': 'acme-lib','version': 'v1.2.3'}", "{'group': 'acme-app','name': 'acme-lib','version': 'v1.2.3'}", true},
//Exact group does not match
new Object[]{PolicyCondition.Operator.MATCHES, "{'group': 'org.hippo','name': 'acme-lib','version': 'v1.2.3'}", "{'group': 'acme-app','name': 'acme-lib','version': 'v1.2.3'}", false},
//Name does not match regex
new Object[]{PolicyCondition.Operator.MATCHES, "{\"group\": \"acme-app\",\"name\": \"*acme-lib*\",\"version\": \"v1.2.3\"}", "{\"group\": \"acme-app\",\"name\": \"good-foo-lib\",\"version\": \"v1.2.3\"}", false},
//Version does not match
new Object[]{PolicyCondition.Operator.MATCHES, "{\"group\": \"acme-app\",\"name\": \"*acme-lib*\",\"version\": \"v1.*\"}", "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v2.2.3\"}", false},
//Does not match on group
new Object[]{PolicyCondition.Operator.NO_MATCH, "{\"group\": \"diff-group\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", true},
//Does not match on version
new Object[]{PolicyCondition.Operator.NO_MATCH, "{\"group\": \"acme-app\",\"name\": \"*acme-lib*\",\"version\": \">=v2.2.2\"}", "{\"group\": \"acme-app\",\"name\": \"acme-lib\",\"version\": \"v1.2.3\"}", true},
new Object[]{PolicyCondition.Operator.MATCHES, "{'group': 'acme-app','name': '*acme-lib*','version': 'v1.2.3'}", "{'group': 'acme-app','name': 'good-foo-lib','version': 'v1.2.3'}", false},
//Version regex does not match
new Object[]{PolicyCondition.Operator.MATCHES, "{'group': 'acme-app','name': '*acme-lib*','version': 'v1.*'}", "{'group': 'acme-app','name': 'acme-lib','version': 'v2.2.3'}", false},
//Does not match on exact group
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'group': 'diff-group','name': 'acme-lib','version': 'v1.2.3'}", "{'group': 'acme-app','name': 'acme-lib','version': 'v1.2.3'}", true},
//Does not match on version range greater than or equal
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'group': 'acme-app','name': '*acme-lib*','version': '>=v2.2.2'}", "{'group': 'acme-app','name': 'acme-lib','version': 'v1.2.3'}", true},
//Matches without group
new Object[]{PolicyCondition.Operator.MATCHES, "{'name': 'Test Component','version': '1.0.0'}", "{'name': 'Test Component','version': '1.0.0'}", true},
//Matches on wild card - uncomment after fixing script builder
//new Object[]{PolicyCondition.Operator.MATCHES, "{ 'group': '*', 'name': 'Test Component', 'version': '1.0.0' }", "{ 'group': 'Anything', 'name': 'Test Component', 'version': '1.0.0' }", false},
//Matches on empty policy - uncomment after fixing script builder
//new Object[]{PolicyCondition.Operator.MATCHES, "{}", "{}", true},
//Does not match on lower version
new Object[]{PolicyCondition.Operator.NO_MATCH, "{ 'version': '== 1.1.1' }", "{'version': '0.1.1'}", true},
//Matches on equal version
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '== 1.1.1' }", "{'version': '1.1.1'}", true},
//Does not match on higher version
new Object[]{PolicyCondition.Operator.NO_MATCH, "{ 'version': '== 1.1.1' }", "{'version': '2.1.1'}", true},
//No match with version not equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '!= 1.1.1' }", "{ 'version': '1.1.1' }", false},
//Matches with version not equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '!= 1.1.1' }", "{'version': '2.1.1'}", true},
//Matches with version not equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '!= 1.1.1' }", "{'version': '0.1.1'}", true},
//Matches with version greater than
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '> 1.1.1' }", "{'version': '2.1.1'}", true},
//Does not match on version greater than
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '> 1.1.1' }", "{'version': '0.1.1'}", false},
//Does not match on version equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{ 'version': '> 1.1.1' }", "{'version': '1.1.1'}", false},
//No match with version greater than
new Object[]{PolicyCondition.Operator.NO_MATCH, "{ 'version': '> 1.1.1' }", "{'version': '0.1.1'}", true},
//No match with version equal to
new Object[]{PolicyCondition.Operator.NO_MATCH, "{ 'version': '> 1.1.1' }", "{'version': '1.1.1'}", true},
//No match with version greater than
new Object[]{PolicyCondition.Operator.NO_MATCH, "{ 'version': '> 1.1.1' }", "{'version': '2.1.1'}", false},
//Matches on version less than
new Object[]{PolicyCondition.Operator.MATCHES, "{'version': '<1.1.1'}", "{'version': '0.1.1'}", true},
//Does not match on version less than
new Object[]{PolicyCondition.Operator.MATCHES, "{'version': '<1.1.1'}", "{'version': '2.1.1'}", false},
//Does not match on equal version
new Object[]{PolicyCondition.Operator.MATCHES, "{'version': '<1.1.1'}", "{'version': '1.1.1'}", false},
//No match on version less than
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'version': '<1.1.1'}", "{'version': '0.1.1'}", false},
//No match on version less than
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'version': '<1.1.1'}", "{'version': '2.1.1'}", true},
//No match on equal version
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'version': '<1.1.1'}", "{'version': '1.1.1'}", true},
//Matches on version less than equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{'version': '<=1.1.1'}", "{'version': '0.1.1'}", true},
//Matches on version less than equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{'version': '<=1.1.1'}", "{'version': '2.1.1'}", false},
//Matches on version less than equal to
new Object[]{PolicyCondition.Operator.MATCHES, "{'version': '<=1.1.1'}", "{'version': '1.1.1'}", true},
//Matches on version less than equal to
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'version': '<=1.1.1'}", "{'version': '0.1.1'}", false},
//Matches on version less than equal to
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'version': '<=1.1.1'}", "{'version': '2.1.1'}", true},
//Matches on version less than equal to
new Object[]{PolicyCondition.Operator.NO_MATCH, "{'version': '<=1.1.1'}", "{'version': '1.1.1'}", false},
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.dependencytrack.policy.cel.compat;

import org.dependencytrack.AbstractPostgresEnabledTest;
import org.dependencytrack.model.Component;
import org.dependencytrack.model.License;
import org.dependencytrack.model.Policy;
import org.dependencytrack.model.PolicyCondition;
import org.dependencytrack.model.Project;
import org.dependencytrack.policy.cel.CelPolicyEngine;
import org.junit.Test;

import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

public class LicenseConditionTest extends AbstractPostgresEnabledTest {

@Test
public void hasMatch() {
License license = new License();
license.setName("Apache 2.0");
license.setUuid(UUID.randomUUID());
license = qm.persist(license);

Policy policy = qm.createPolicy("Test Policy", Policy.Operator.ANY, Policy.ViolationState.INFO);
qm.createPolicyCondition(policy, PolicyCondition.Subject.LICENSE, PolicyCondition.Operator.IS, license.getUuid().toString());
final var project = new Project();
project.setName("acme-app");
qm.persist(project);

final var component = new Component();
component.setName("acme-app");
component.setResolvedLicense(license);
component.setProject(project);
qm.persist(component);

new CelPolicyEngine().evaluateProject(project.getUuid());
assertThat(qm.getAllPolicyViolations(component)).hasSize(1);
}

@Test
public void noMatch() {
License license = new License();
license.setName("Apache 2.0");
license.setUuid(UUID.randomUUID());
license = qm.persist(license);

Policy policy = qm.createPolicy("Test Policy", Policy.Operator.ANY, Policy.ViolationState.INFO);
qm.createPolicyCondition(policy, PolicyCondition.Subject.LICENSE, PolicyCondition.Operator.IS, UUID.randomUUID().toString());
final var project = new Project();
project.setName("acme-app");
qm.persist(project);

final var component = new Component();
component.setName("acme-app");
component.setResolvedLicense(license);
component.setProject(project);

qm.persist(component);

new CelPolicyEngine().evaluateProject(project.getUuid());
assertThat(qm.getAllPolicyViolations(component)).isEmpty();
}

@Test
public void wrongOperator() {
License license = new License();
license.setName("Apache 2.0");
license.setUuid(UUID.randomUUID());
license = qm.persist(license);

Policy policy = qm.createPolicy("Test Policy", Policy.Operator.ANY, Policy.ViolationState.INFO);
qm.createPolicyCondition(policy, PolicyCondition.Subject.LICENSE, PolicyCondition.Operator.MATCHES, license.getUuid().toString());
final var project = new Project();
project.setName("acme-app");
qm.persist(project);

final var component = new Component();
component.setName("acme-app");
component.setProject(project);
component.setResolvedLicense(license);
qm.persist(component);

new CelPolicyEngine().evaluateProject(project.getUuid());
assertThat(qm.getAllPolicyViolations(component)).isEmpty();
}

@Test
public void valueIsUnresolved() {
License license = new License();
license.setName("Apache 2.0");
license.setUuid(UUID.randomUUID());
license = qm.persist(license);

Policy policy = qm.createPolicy("Test Policy", Policy.Operator.ANY, Policy.ViolationState.INFO);
qm.createPolicyCondition(policy, PolicyCondition.Subject.LICENSE, PolicyCondition.Operator.IS, "unresolved");

final var project = new Project();
project.setName("acme-app");
qm.persist(project);

Component componentWithoutLicense = new Component();
componentWithoutLicense.setName("second-component");
componentWithoutLicense.setProject(project);
qm.persist(componentWithoutLicense);

CelPolicyEngine policyEngine = new CelPolicyEngine();

policyEngine.evaluateProject(project.getUuid());
assertThat(qm.getAllPolicyViolations(componentWithoutLicense)).hasSize(1);

final var componentWithLicense = new Component();
componentWithLicense.setName("acme-app");
componentWithLicense.setProject(project);
componentWithLicense.setResolvedLicense(license);
qm.persist(componentWithLicense);

policyEngine.evaluateProject(project.getUuid());
assertThat(qm.getAllPolicyViolations(componentWithLicense)).hasSize(0);
}
}

Loading

0 comments on commit d19301c

Please sign in to comment.