Skip to content

Commit

Permalink
Merge pull request #3499 from nscuro/issue-2715
Browse files Browse the repository at this point in the history
Add support for component properties
  • Loading branch information
nscuro authored Apr 14, 2024
2 parents 7099bac + 11020d1 commit 9384714
Show file tree
Hide file tree
Showing 17 changed files with 1,353 additions and 55 deletions.
5 changes: 4 additions & 1 deletion docs/_posts/2024-xx-xx-v4.11.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Community input and contributions are explicitly requested. The chart repository
* Add attribution notice to NVD documentation - [apiserver/#3490]
* Bump CWE dictionary to v4.13 - [apiserver/#3491]
* Align retry configuration and behavior across analyzers - [apiserver/#3494]
* Add support for component properties - [apiserver/#3499]
* Add auto-generated changelog to GitHub releases - [apiserver/#3502]
* Bump SPDX license list to v3.23 - [apiserver/#3508]
* Validate uploaded BOMs against CycloneDX schema prior to processing them - [apiserver/#3522]
Expand Down Expand Up @@ -157,7 +158,7 @@ We thank all organizations and individuals who contributed to this release, from
Special thanks to everyone who contributed code to implement enhancements and fix defects:
[@AnthonyMastrean], [@LaVibeX], [@MangoIV], [@Robbilie], [@VithikaS], [@a5a351e7], [@acdha], [@aravindparappil46],
[@baburkin], [@fnxpt], [@kepten], [@leec94], [@lukas-braune], [@malice00], [@mehab], [@mge-mm]
[@mikkeschiren], [@mykter], [@rbt-mm], [@rkg-mm], [@sahibamittal], [@sebD], [@setchy]
[@mikkeschiren], [@mykter], [@rbt-mm], [@rkesters], [@rkg-mm], [@sahibamittal], [@sebD], [@setchy]

###### dependency-track-apiserver.jar

Expand Down Expand Up @@ -209,6 +210,7 @@ Special thanks to everyone who contributed code to implement enhancements and fi
[apiserver/#3490]: https://github.com/DependencyTrack/dependency-track/pull/3490
[apiserver/#3491]: https://github.com/DependencyTrack/dependency-track/pull/3491
[apiserver/#3494]: https://github.com/DependencyTrack/dependency-track/pull/3494
[apiserver/#3499]: https://github.com/DependencyTrack/dependency-track/pull/3499
[apiserver/#3502]: https://github.com/DependencyTrack/dependency-track/pull/3502
[apiserver/#3508]: https://github.com/DependencyTrack/dependency-track/pull/3508
[apiserver/#3511]: https://github.com/DependencyTrack/dependency-track/pull/3511
Expand Down Expand Up @@ -280,6 +282,7 @@ Special thanks to everyone who contributed code to implement enhancements and fi
[@mprencipe]: https://github.com/mprencipe
[@mykter]: https://github.com/mykter
[@rbt-mm]: https://github.com/rbt-mm
[@rkesters]: https://github.com/rkesters
[@rkg-mm]: https://github.com/rkg-mm
[@sahibamittal]: https://github.com/sahibamittal
[@sebD]: https://github.com/sebD
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/dependencytrack/model/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
@Persistent(name = "externalReferences"),
@Persistent(name = "parent"),
@Persistent(name = "children"),
@Persistent(name = "properties"),
@Persistent(name = "vulnerabilities"),
}),
@FetchGroup(name = "INTERNAL_IDENTIFICATION", members = {
Expand Down Expand Up @@ -330,6 +331,10 @@ public enum FetchGroup {
@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "id ASC"))
private Collection<Component> children;

@Persistent(mappedBy = "component", defaultFetchGroup = "false")
@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "groupName ASC, propertyName ASC, id ASC"))
private List<ComponentProperty> properties;

@Persistent(table = "COMPONENTS_VULNERABILITIES")
@Join(column = "COMPONENT_ID")
@Element(column = "VULNERABILITY_ID")
Expand Down Expand Up @@ -712,6 +717,14 @@ public void setChildren(Collection<Component> children) {
this.children = children;
}

public List<ComponentProperty> getProperties() {
return properties;
}

public void setProperties(final List<ComponentProperty> properties) {
this.properties = properties;
}

public List<Vulnerability> getVulnerabilities() {
return vulnerabilities;
}
Expand Down
195 changes: 195 additions & 0 deletions src/main/java/org/dependencytrack/model/ComponentProperty.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/*
* 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.model;

import alpine.model.IConfigProperty;
import alpine.server.json.TrimmedStringDeserializer;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.MoreObjects;
import org.dependencytrack.model.validation.EnumValue;

import javax.jdo.annotations.Column;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import javax.jdo.annotations.Unique;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.UUID;

/**
* @since 4.11.0
*/
@PersistenceCapable(table = "COMPONENT_PROPERTY")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ComponentProperty implements IConfigProperty, Serializable {

private static final long serialVersionUID = -7510889645969713080L;

public record Identity(String group, String name, String value) {

public Identity(final ComponentProperty property) {
this(property.getGroupName(), property.getPropertyName(), property.getPropertyValue());
}

}

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.NATIVE)
@JsonIgnore
private long id;

@Persistent
@Column(name = "COMPONENT_ID", allowsNull = "false")
@JsonIgnore
private Component component;

@Persistent
@Column(name = "GROUPNAME")
@Size(min = 1, max = 255)
@JsonDeserialize(using = TrimmedStringDeserializer.class)
@Pattern(regexp = "\\P{Cc}+", message = "The groupName must not contain control characters")
private String groupName;

@Persistent
@Column(name = "PROPERTYNAME", allowsNull = "false")
@NotBlank
@Size(min = 1, max = 255)
@JsonDeserialize(using = TrimmedStringDeserializer.class)
@Pattern(regexp = "\\P{Cc}+", message = "The propertyName must not contain control characters")
private String propertyName;

@Persistent
@Column(name = "PROPERTYVALUE", length = 1024)
@Size(max = 1024)
@JsonDeserialize(using = TrimmedStringDeserializer.class)
@Pattern(regexp = "\\P{Cc}+", message = "The propertyValue must not contain control characters")
private String propertyValue;

@Persistent
@Column(name = "PROPERTYTYPE", jdbcType = "VARCHAR", allowsNull = "false")
@NotNull
// NB: Encrypted values are disallowed because it complicates identity management.
// Because duplicate groupName/propertyName combinations are allowed, the value
// is critical to determine property uniqueness. We'd need to decrypt encrypted
// values prior to uniqueness checks. We'd also open the door for attackers to
// guess the encrypted value. As of now, there is no known use-case for encrypted
// properties on the component level.
@EnumValue(disallowed = "ENCRYPTEDSTRING", message = "Encrypted component property values are not supported")
private PropertyType propertyType;

@Persistent
@Column(name = "DESCRIPTION")
@Size(max = 255)
@JsonDeserialize(using = TrimmedStringDeserializer.class)
@Pattern(regexp = "\\P{Cc}+", message = "The description must not contain control characters")
private String description;

@Persistent(customValueStrategy = "uuid")
@Unique(name = "COMPONENT_PROPERTY_UUID_IDX")
@Column(name = "UUID", jdbcType = "VARCHAR", length = 36, allowsNull = "false")
@NotNull
private UUID uuid;

public long getId() {
return id;
}

public void setId(final long id) {
this.id = id;
}

public Component getComponent() {
return component;
}

public void setComponent(final Component component) {
this.component = component;
}

public String getGroupName() {
return groupName;
}

public void setGroupName(final String groupName) {
this.groupName = groupName;
}

public String getPropertyName() {
return propertyName;
}

public void setPropertyName(final String propertyName) {
this.propertyName = propertyName;
}

public String getPropertyValue() {
return propertyValue;
}

public void setPropertyValue(final String propertyValue) {
this.propertyValue = propertyValue;
}

public PropertyType getPropertyType() {
return propertyType;
}

public void setPropertyType(final PropertyType propertyType) {
this.propertyType = propertyType;
}

public String getDescription() {
return description;
}

public void setDescription(final String description) {
this.description = description;
}

public UUID getUuid() {
return uuid;
}

public void setUuid(final UUID uuid) {
this.uuid = uuid;
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("component", component)
.add("groupName", groupName)
.add("propertyName", propertyName)
.add("propertyValue", propertyValue)
.add("propertyType", propertyType)
.add("description", description)
.add("uuid", uuid)
.omitNullValues()
.toString();
}

}
43 changes: 43 additions & 0 deletions src/main/java/org/dependencytrack/model/validation/EnumValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.model.validation;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* @since 4.11.0
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Constraint(validatedBy = EnumValueValidator.class)
public @interface EnumValue {

String[] disallowed() default {};
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.model.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.Set;

/**
* @since 4.11.0
*/
public class EnumValueValidator implements ConstraintValidator<EnumValue, Enum<?>> {

private Set<String> disallowedValues;

@Override
public void initialize(final EnumValue constraintAnnotation) {
disallowedValues = Set.copyOf(Arrays.asList(constraintAnnotation.disallowed()));
}

@Override
public boolean isValid(final Enum<?> value, final ConstraintValidatorContext context) {
if (value == null) {
return true;
}

return !disallowedValues.contains(value.name());
}

}
Loading

0 comments on commit 9384714

Please sign in to comment.