Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/org/dependencytrack/model/PolicyCondition.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@ public enum Subject {
SEVERITY,
SWID_TAGID,
VERSION,
IS_INTERNAL,
COMPONENT_HASH,
CWE,
VULNERABILITY_ID,
VERSION_DISTANCE,
LATEST_VERSION_STATUS,
EPSS
}

Expand Down Expand Up @@ -184,3 +186,4 @@ public void setUuid(UUID uuid) {
this.uuid = uuid;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* This file is part of Dependency-Track.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) OWASP Foundation. All Rights Reserved.
*/
package org.dependencytrack.policy;

import org.dependencytrack.model.Component;
import org.dependencytrack.model.Policy;
import org.dependencytrack.model.PolicyCondition;

import java.util.ArrayList;
import java.util.List;

/**
* Evaluates whether a component's internal status matches a given policy.
*/
public class InternalStatusPolicyEvaluator extends AbstractPolicyEvaluator {

@Override
public PolicyCondition.Subject supportedSubject() {
return PolicyCondition.Subject.IS_INTERNAL;
}

@Override
public List<PolicyConditionViolation> evaluate(final Policy policy, final Component component) {
final List<PolicyConditionViolation> violations = new ArrayList<>();

for (final PolicyCondition condition : super.extractSupportedConditions(policy)) {

final boolean isInternal = Boolean.TRUE.equals(component.isInternal());
final boolean expectedInternal = Boolean.parseBoolean(condition.getValue());

switch (condition.getOperator()) {
case IS:
if (isInternal == expectedInternal) {
violations.add(new PolicyConditionViolation(condition, component));
}
break;
case IS_NOT:
if (isInternal != expectedInternal) {
violations.add(new PolicyConditionViolation(condition, component));
}
break;
}
}
return violations;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* This file is part of Dependency-Track.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) OWASP Foundation. All Rights Reserved.
*/
package org.dependencytrack.policy;

import com.github.packageurl.PackageURL;
import org.dependencytrack.model.Component;
import org.dependencytrack.model.Policy;
import org.dependencytrack.model.PolicyCondition;
import org.dependencytrack.model.RepositoryMetaComponent;
import org.dependencytrack.model.RepositoryType;

import java.util.ArrayList;
import java.util.List;

public class LatestVersionPolicyEvaluator extends AbstractPolicyEvaluator {

private static final String STATE_LATEST = "LATEST";
private static final String STATE_OUTDATED = "OUTDATED";
private static final String STATE_UNKNOWN = "UNKNOWN";

@Override
public List<PolicyConditionViolation> evaluate(final Policy policy, final Component component) {

final List<PolicyConditionViolation> violations = new ArrayList<>();

for (final PolicyCondition condition : extractSupportedConditions(policy)) {

final String expected = normalize(condition.getValue());

RepositoryMetaComponent meta = component.getRepositoryMeta();

if (meta == null && qm != null) {
final PackageURL purl = component.getPurlCoordinates();
if (purl != null) {
final RepositoryType repoType = toRepositoryType(purl.getType());
final String namespace = purl.getNamespace();
final String name = purl.getName();

if (repoType != null && name != null) {

Check notice on line 55 in src/main/java/org/dependencytrack/policy/LatestVersionPolicyEvaluator.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/org/dependencytrack/policy/LatestVersionPolicyEvaluator.java#L55

Deeply nested if..then statements are hard to read
meta = qm.getRepositoryMetaComponent(repoType, namespace, name);
}
}
}

final String current = component.getVersion();
final String latest = (meta != null) ? meta.getLatestVersion() : null;

final String actualState;
if (meta == null || current == null || latest == null) {
actualState = STATE_UNKNOWN;
} else if (current.equals(latest)) {
actualState = STATE_LATEST;
} else {
actualState = STATE_OUTDATED;
}

final boolean matches = actualState.equals(expected);

if (condition.getOperator() == PolicyCondition.Operator.IS) {
if (matches) {
violations.add(new PolicyConditionViolation(condition, component));
}
} else if (condition.getOperator() == PolicyCondition.Operator.IS_NOT) {
if (!matches) {
violations.add(new PolicyConditionViolation(condition, component));
}
}
}

return violations;
}

@Override
public PolicyCondition.Subject supportedSubject() {
return PolicyCondition.Subject.LATEST_VERSION_STATUS;
}

private static String normalize(final String v) {
return v == null ? null : v.trim().toUpperCase();
}

private static RepositoryType toRepositoryType(final String purlType) {
return RepositoryType.valueOf(purlType.trim().toUpperCase());
}
}
6 changes: 4 additions & 2 deletions src/main/java/org/dependencytrack/policy/PolicyEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public PolicyEngine() {
evaluators.add(new VulnerabilityIdPolicyEvaluator());
evaluators.add(new VersionDistancePolicyEvaluator());
evaluators.add(new EpssPolicyEvaluator());
evaluators.add(new InternalStatusPolicyEvaluator());
evaluators.add(new LatestVersionPolicyEvaluator());
}

public List<PolicyViolation> evaluate(final List<Component> components) {
Expand Down Expand Up @@ -145,7 +147,7 @@ public PolicyViolation.Type determineViolationType(final PolicyCondition.Subject
}
return switch (subject) {
case CWE, SEVERITY, VULNERABILITY_ID, EPSS -> PolicyViolation.Type.SECURITY;
case AGE, COORDINATES, PACKAGE_URL, CPE, SWID_TAGID, COMPONENT_HASH, VERSION, VERSION_DISTANCE ->
case AGE, COORDINATES, PACKAGE_URL, CPE, SWID_TAGID, COMPONENT_HASH, VERSION, VERSION_DISTANCE, IS_INTERNAL , LATEST_VERSION_STATUS ->
PolicyViolation.Type.OPERATIONAL;
case LICENSE, LICENSE_GROUP -> PolicyViolation.Type.LICENSE;
};
Expand Down Expand Up @@ -176,4 +178,4 @@ private boolean isPolicyAssignedToParentProject(Policy policy, Project child) {
}
return isPolicyAssignedToParentProject(policy, child.getParent());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* This file is part of Dependency-Track.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) OWASP Foundation. All Rights Reserved.
*/

package org.dependencytrack.policy;

import org.dependencytrack.model.Component;
import org.dependencytrack.model.Policy;
import org.dependencytrack.model.PolicyCondition;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

Check warning on line 30 in src/test/java/org/dependencytrack/policy/InternalStatusPolicyEvaluatorTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/test/java/org/dependencytrack/policy/InternalStatusPolicyEvaluatorTest.java#L30

Using the '.*' form of import should be avoided - org.junit.jupiter.api.Assertions.*.

class InternalStatusPolicyEvaluatorTest {

private InternalStatusPolicyEvaluator evaluator;

@BeforeEach
void setUp() {
evaluator = new InternalStatusPolicyEvaluator();
}

private Policy policyWith(PolicyCondition condition) {
Policy policy = new Policy();
policy.setViolationState(Policy.ViolationState.FAIL);
policy.addPolicyCondition(condition);
return policy;
}

@Test
void testIsTrue_NoViolationWhenInternal() {
Component component = new Component();
component.setInternal(true);

PolicyCondition condition = new PolicyCondition();
condition.setSubject(PolicyCondition.Subject.IS_INTERNAL);
condition.setOperator(PolicyCondition.Operator.IS);
condition.setValue("true");

Policy policy = policyWith(condition);
List<PolicyConditionViolation> result = evaluator.evaluate(policy, component);

assertFalse(result.isEmpty());
}

@Test
void testIsTrue_ViolationWhenNotInternal() {
Component component = new Component();
component.setInternal(false);

PolicyCondition condition = new PolicyCondition();
condition.setSubject(PolicyCondition.Subject.IS_INTERNAL);
condition.setOperator(PolicyCondition.Operator.IS);
condition.setValue("true");

Policy policy = policyWith(condition);
List<PolicyConditionViolation> result = evaluator.evaluate(policy, component);

assertEquals(0, result.size());
}

@Test
void testIsNotTrue_ViolationWhenInternal() {
Component component = new Component();
component.setInternal(true);

PolicyCondition condition = new PolicyCondition();
condition.setSubject(PolicyCondition.Subject.IS_INTERNAL);
condition.setOperator(PolicyCondition.Operator.IS_NOT);
condition.setValue("true");

Policy policy = policyWith(condition);
List<PolicyConditionViolation> result = evaluator.evaluate(policy, component);

assertEquals(0, result.size());
}

@Test
void testIsNotTrue_NoViolationWhenNotInternal() {
Component component = new Component();
component.setInternal(false);

PolicyCondition condition = new PolicyCondition();
condition.setSubject(PolicyCondition.Subject.IS_INTERNAL);
condition.setOperator(PolicyCondition.Operator.IS_NOT);
condition.setValue("true");

Policy policy = policyWith(condition);
List<PolicyConditionViolation> result = evaluator.evaluate(policy, component);

assertFalse(result.isEmpty());
}
}
Loading
Loading