diff --git a/src/main/java/org/cyclonedx/generators/AbstractBomGenerator.java b/src/main/java/org/cyclonedx/generators/AbstractBomGenerator.java index 6b672111e5..e503166798 100644 --- a/src/main/java/org/cyclonedx/generators/AbstractBomGenerator.java +++ b/src/main/java/org/cyclonedx/generators/AbstractBomGenerator.java @@ -11,6 +11,7 @@ import org.cyclonedx.util.serializer.LifecycleSerializer; import org.cyclonedx.util.serializer.MetadataSerializer; import org.cyclonedx.util.serializer.OutputTypeSerializer; +import org.cyclonedx.util.serializer.SignatorySerializer; public abstract class AbstractBomGenerator extends CycloneDxSchema { @@ -58,5 +59,9 @@ protected void setupObjectMapper(boolean isXml) { SimpleModule evidenceModule = new SimpleModule(); evidenceModule.addSerializer(new EvidenceSerializer(isXml, getSchemaVersion())); mapper.registerModule(evidenceModule); + + SimpleModule signatoryModule = new SimpleModule(); + signatoryModule.addSerializer(new SignatorySerializer(isXml)); + mapper.registerModule(signatoryModule); } } diff --git a/src/main/java/org/cyclonedx/model/Bom.java b/src/main/java/org/cyclonedx/model/Bom.java index cb170bc481..749a61e340 100644 --- a/src/main/java/org/cyclonedx/model/Bom.java +++ b/src/main/java/org/cyclonedx/model/Bom.java @@ -30,6 +30,8 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import org.cyclonedx.Version; +import org.cyclonedx.model.attestation.Declarations; +import org.cyclonedx.model.definition.Definition; import org.cyclonedx.model.formulation.Formula; import org.cyclonedx.model.vulnerability.Vulnerability; import org.cyclonedx.util.deserializer.DependencyDeserializer; @@ -55,6 +57,8 @@ "vulnerabilities", "annotations", "formulation", + "declarations", + "definitions", "signature" }) public class Bom extends ExtensibleElement { @@ -84,6 +88,12 @@ public class Bom extends ExtensibleElement { @VersionFilter(Version.VERSION_15) private List formulation; + @VersionFilter(Version.VERSION_16) + private Definition definitions; + + @VersionFilter(Version.VERSION_16) + private Declarations declarations; + @VersionFilter(Version.VERSION_14) @JsonDeserialize(using = VulnerabilityDeserializer.class) private List vulnerabilities; @@ -237,6 +247,22 @@ public void addProperty(Property property) { this.properties.add(property); } + public Declarations getDeclarations() { + return declarations; + } + + public void setDeclarations(final Declarations declarations) { + this.declarations = declarations; + } + + public Definition getDefinitions() { + return definitions; + } + + public void setDefinitions(final Definition definitions) { + this.definitions = definitions; + } + public int getVersion() { return version; } diff --git a/src/main/java/org/cyclonedx/model/ExternalReference.java b/src/main/java/org/cyclonedx/model/ExternalReference.java index 31c32a13ba..a3c618629a 100644 --- a/src/main/java/org/cyclonedx/model/ExternalReference.java +++ b/src/main/java/org/cyclonedx/model/ExternalReference.java @@ -117,6 +117,12 @@ public enum Type { FORMULATION("formulation"), @JsonProperty("rfc-9116") RFC_9116("rfc-9116"), + @VersionFilter(Version.VERSION_16) + @JsonProperty("electronic-signature") + ELECTRONIC_SIGNATURE("electronic-signature"), + @VersionFilter(Version.VERSION_16) + @JsonProperty("digital-signature") + DIGITAL_SIGNATURE("digital-signature"), @JsonProperty("other") OTHER("other"); diff --git a/src/main/java/org/cyclonedx/model/Service.java b/src/main/java/org/cyclonedx/model/Service.java index b692f996d8..532dad38a1 100644 --- a/src/main/java/org/cyclonedx/model/Service.java +++ b/src/main/java/org/cyclonedx/model/Service.java @@ -75,7 +75,7 @@ public class Service extends ExtensibleElement { private List externalReferences; @VersionFilter(Version.VERSION_13) private List properties; - @VersionFilter(value = Version.VERSION_16) + @VersionFilter(Version.VERSION_16) @JsonUnwrapped private Tags tags; private List services; diff --git a/src/main/java/org/cyclonedx/model/attestation/Assessor.java b/src/main/java/org/cyclonedx/model/attestation/Assessor.java new file mode 100644 index 0000000000..cb04bf16b9 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Assessor.java @@ -0,0 +1,49 @@ +package org.cyclonedx.model.attestation; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.OrganizationalEntity; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "thirdParty", + "organization" +}) +public class Assessor +{ + @JacksonXmlProperty(isAttribute = true, localName = "bom-ref") + @JsonProperty("bom-ref") + private String bomRef; + + private Boolean thirdParty; + + private OrganizationalEntity organization; + + public String getBomRef() { + return bomRef; + } + + public void setBomRef(final String bomRef) { + this.bomRef = bomRef; + } + + public Boolean getThirdParty() { + return thirdParty; + } + + public void setThirdParty(final Boolean thirdParty) { + this.thirdParty = thirdParty; + } + + public OrganizationalEntity getOrganization() { + return organization; + } + + public void setOrganization(final OrganizationalEntity organization) { + this.organization = organization; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/Attestation.java b/src/main/java/org/cyclonedx/model/attestation/Attestation.java new file mode 100644 index 0000000000..15e9c6e8e0 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Attestation.java @@ -0,0 +1,63 @@ +package org.cyclonedx.model.attestation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.Signature; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "summary", + "assessor", + "mapList", + "signature" +}) +public class Attestation +{ + private String summary; + + @JacksonXmlProperty(isAttribute = true, localName = "assessor") + @JsonProperty("assessor") + private String assessor; + + private List mapList; + + private Signature signature; + + public String getSummary() { + return summary; + } + + public void setSummary(final String summary) { + this.summary = summary; + } + + public String getAssessor() { + return assessor; + } + + public void setAssessor(final String assessor) { + this.assessor = assessor; + } + + public List getMapList() { + return mapList; + } + + public void setMapList(final List mapList) { + this.mapList = mapList; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/AttestationMap.java b/src/main/java/org/cyclonedx/model/attestation/AttestationMap.java new file mode 100644 index 0000000000..35dfed7156 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/AttestationMap.java @@ -0,0 +1,80 @@ +package org.cyclonedx.model.attestation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +@JacksonXmlRootElement(localName = "map") +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "requirement", + "claims", + "counterClaims", + "conformance", + "confidence" +}) +public class AttestationMap +{ + @JacksonXmlProperty(isAttribute = true, localName = "requirement") + @JsonProperty("requirement") + private String requirement; + + private List claims; + + private List counterClaims; + + private Conformance conformance; + + private Confidence confidence; + + public String getRequirement() { + return requirement; + } + + public void setRequirement(final String requirement) { + this.requirement = requirement; + } + + @JacksonXmlElementWrapper(localName = "claims") + @JacksonXmlProperty(localName = "claim") + public List getClaims() { + return claims; + } + + public void setClaims(final List claims) { + this.claims = claims; + } + + @JacksonXmlElementWrapper(localName = "counterClaims") + @JacksonXmlProperty(localName = "counterClaim") + public List getCounterClaims() { + return counterClaims; + } + + public void setCounterClaims(final List counterClaims) { + this.counterClaims = counterClaims; + } + + public Conformance getConformance() { + return conformance; + } + + public void setConformance(final Conformance conformance) { + this.conformance = conformance; + } + + public Confidence getConfidence() { + return confidence; + } + + public void setConfidence(final Confidence confidence) { + this.confidence = confidence; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/Claim.java b/src/main/java/org/cyclonedx/model/attestation/Claim.java new file mode 100644 index 0000000000..8168b408f1 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Claim.java @@ -0,0 +1,127 @@ +package org.cyclonedx.model.attestation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.ExternalReference; +import org.cyclonedx.model.Signature; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "target", + "predicate", + "mitigationStrategies", + "reasoning", + "evidence", + "counterEvidence", + "externalReferences", + "signature" +}) +public class Claim +{ + @JacksonXmlProperty(isAttribute = true, localName = "bom-ref") + @JsonProperty("bom-ref") + private String bomRef; + + private String target; + + private String predicate; + + private List mitigationStrategies; + + private String reasoning; + + private List evidence; + + private List counterEvidence; + + private List externalReferences; + + private Signature signature; + + public String getBomRef() { + return bomRef; + } + + public void setBomRef(final String bomRef) { + this.bomRef = bomRef; + } + + public String getTarget() { + return target; + } + + public void setTarget(final String target) { + this.target = target; + } + + public String getPredicate() { + return predicate; + } + + public void setPredicate(final String predicate) { + this.predicate = predicate; + } + + @JacksonXmlElementWrapper(localName = "mitigationStrategies") + @JacksonXmlProperty(localName = "mitigationStrategy") + public List getMitigationStrategies() { + return mitigationStrategies; + } + + public void setMitigationStrategies(final List mitigationStrategies) { + this.mitigationStrategies = mitigationStrategies; + } + + public String getReasoning() { + return reasoning; + } + + public void setReasoning(final String reasoning) { + this.reasoning = reasoning; + } + + @JacksonXmlElementWrapper(localName = "evidences") + @JacksonXmlProperty(localName = "evidence") + public List getEvidence() { + return evidence; + } + + public void setEvidence(final List evidence) { + this.evidence = evidence; + } + + @JacksonXmlElementWrapper(localName = "counterEvidences") + @JacksonXmlProperty(localName = "counterEvidence") + public List getCounterEvidence() { + return counterEvidence; + } + + public void setCounterEvidence(final List counterEvidence) { + this.counterEvidence = counterEvidence; + } + + @JacksonXmlElementWrapper(localName = "externalReferences") + @JacksonXmlProperty(localName = "externalReference") + public List getExternalReferences() { + return externalReferences; + } + + public void setExternalReferences(final List externalReferences) { + this.externalReferences = externalReferences; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/Confidence.java b/src/main/java/org/cyclonedx/model/attestation/Confidence.java new file mode 100644 index 0000000000..a888a963c0 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Confidence.java @@ -0,0 +1,36 @@ +package org.cyclonedx.model.attestation; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "score", + "rationale" +}) +public class Confidence +{ + private Integer score; + + private String rationale; + + + public Integer getScore() { + return score; + } + + public void setScore(final Integer score) { + this.score = score; + } + + public String getRationale() { + return rationale; + } + + public void setRationale(final String rationale) { + this.rationale = rationale; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/Conformance.java b/src/main/java/org/cyclonedx/model/attestation/Conformance.java new file mode 100644 index 0000000000..cddf11c3bf --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Conformance.java @@ -0,0 +1,50 @@ +package org.cyclonedx.model.attestation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "score", + "rationale", + "mitigationStrategies" +}) +public class Conformance +{ + private Integer score; + + private String rationale; + + private List mitigationStrategies; + + public Integer getScore() { + return score; + } + + public void setScore(final Integer score) { + this.score = score; + } + + public String getRationale() { + return rationale; + } + + public void setRationale(final String rationale) { + this.rationale = rationale; + } + @JacksonXmlElementWrapper(localName = "mitigationStrategies") + @JacksonXmlProperty(localName = "mitigationStrategy") + public List getMitigationStrategies() { + return mitigationStrategies; + } + + public void setMitigationStrategies(final List mitigationStrategies) { + this.mitigationStrategies = mitigationStrategies; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/Declarations.java b/src/main/java/org/cyclonedx/model/attestation/Declarations.java new file mode 100644 index 0000000000..6146d1cc90 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Declarations.java @@ -0,0 +1,102 @@ +package org.cyclonedx.model.attestation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.Signature; +import org.cyclonedx.model.attestation.affirmation.Affirmation; +import org.cyclonedx.model.attestation.evidence.Evidence; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "assessors", + "attestations", + "claims", + "evidence", + "targets", + "affirmation", + "signature" +}) +public class Declarations +{ + private List assessors; + + private List attestations; + + private List claims; + + private List evidence; + + private Targets targets; + + private Affirmation affirmation; + + private Signature signature; + + public List getAssessors() { + return assessors; + } + + public void setAssessors(final List assessors) { + this.assessors = assessors; + } + + @JacksonXmlElementWrapper(localName = "attestations") + @JacksonXmlProperty(localName = "attestation") + public List getAttestations() { + return attestations; + } + + public void setAttestations(final List attestations) { + this.attestations = attestations; + } + + @JacksonXmlElementWrapper(localName = "claims") + @JacksonXmlProperty(localName = "claim") + public List getClaims() { + return claims; + } + + public void setClaims(final List claims) { + this.claims = claims; + } + + @JacksonXmlElementWrapper(localName = "evidence") + @JacksonXmlProperty(localName = "evidence") + public List getEvidence() { + return evidence; + } + + public void setEvidence(final List evidence) { + this.evidence = evidence; + } + + public Targets getTargets() { + return targets; + } + + public void setTargets(final Targets targets) { + this.targets = targets; + } + + public Affirmation getAffirmation() { + return affirmation; + } + + public void setAffirmation(final Affirmation affirmation) { + this.affirmation = affirmation; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/Targets.java b/src/main/java/org/cyclonedx/model/attestation/Targets.java new file mode 100644 index 0000000000..7a3b536650 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/Targets.java @@ -0,0 +1,58 @@ +package org.cyclonedx.model.attestation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.Component; +import org.cyclonedx.model.OrganizationalEntity; +import org.cyclonedx.model.Service; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "organizations", + "components", + "services" +}) +public class Targets +{ + private List organizations; + + private List components; + + private List services; + + @JacksonXmlElementWrapper(localName = "organizations") + @JacksonXmlProperty(localName = "organization") + public List getOrganizations() { + return organizations; + } + + public void setOrganizations(final List organizations) { + this.organizations = organizations; + } + + @JacksonXmlElementWrapper(localName = "components") + @JacksonXmlProperty(localName = "component") + public List getComponents() { + return components; + } + + public void setComponents(final List components) { + this.components = components; + } + + @JacksonXmlElementWrapper(localName = "services") + @JacksonXmlProperty(localName = "service") + public List getServices() { + return services; + } + + public void setServices(final List services) { + this.services = services; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/affirmation/Affirmation.java b/src/main/java/org/cyclonedx/model/attestation/affirmation/Affirmation.java new file mode 100644 index 0000000000..dd4ddd998c --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/affirmation/Affirmation.java @@ -0,0 +1,52 @@ +package org.cyclonedx.model.attestation.affirmation; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.Signature; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "statement", + "signatories", + "signature" +}) +public class Affirmation +{ + private String statement; + + private List signatories; + + private Signature signature; + + public String getStatement() { + return statement; + } + + public void setStatement(final String statement) { + this.statement = statement; + } + + @JacksonXmlProperty(localName = "signatory") + @JacksonXmlElementWrapper(useWrapping = false) + public List getSignatories() { + return signatories; + } + + public void setSignatories(final List signatories) { + this.signatories = signatories; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/affirmation/Signatory.java b/src/main/java/org/cyclonedx/model/attestation/affirmation/Signatory.java new file mode 100644 index 0000000000..17e61dfd94 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/affirmation/Signatory.java @@ -0,0 +1,86 @@ +package org.cyclonedx.model.attestation.affirmation; + +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.cyclonedx.model.ExternalReference; +import org.cyclonedx.model.OrganizationalEntity; +import org.cyclonedx.model.Signature; +import org.cyclonedx.util.deserializer.SignatoryDeserializer; + +@JsonTypeName("signatory") +@JsonSubTypes({ + @JsonSubTypes.Type(value = Signature.class, name = "signature"), + @JsonSubTypes.Type(value = OrganizationalEntity.class, name = "organization"), + @JsonSubTypes.Type(value = ExternalReference.class, name = "externalReference") +}) +@JsonDeserialize(using = SignatoryDeserializer.class) +public class Signatory +{ + private String name; + + private String role; + + private Signature signature; + + private OrganizationalEntity organization; + private ExternalReference externalReference; + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getRole() { + return role; + } + + public void setRole(final String role) { + this.role = role; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + + //If Signature is present organization and external reference are not allowed + organization = null; + externalReference = null; + } + + public OrganizationalEntity getOrganization() { + return organization; + } + + public void setOrganization(final OrganizationalEntity organization) { + this.organization = organization; + //if organization and external reference are present signature is not allowed + signature = null; + } + + public ExternalReference getExternalReference() { + return externalReference; + } + + public void setExternalReference(final ExternalReference externalReference) { + this.externalReference = externalReference; + //if organization and external reference are present signature is not allowed + signature = null; + } + + public void setExternalReferenceAndOrganization( + final ExternalReference externalReference, + final OrganizationalEntity organization) + { + this.organization = organization; + this.externalReference = externalReference; + //if organization and external reference are present signature is not allowed + signature = null; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/evidence/Contents.java b/src/main/java/org/cyclonedx/model/attestation/evidence/Contents.java new file mode 100644 index 0000000000..9ad1310bb9 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/evidence/Contents.java @@ -0,0 +1,36 @@ +package org.cyclonedx.model.attestation.evidence; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import org.cyclonedx.model.AttachmentText; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "attachment", + "url", +}) +public class Contents +{ + private AttachmentText attachment; + + private String url; + + public AttachmentText getAttachment() { + return attachment; + } + + public void setAttachment(final AttachmentText attachment) { + this.attachment = attachment; + } + + public String getUrl() { + return url; + } + + public void setUrl(final String url) { + this.url = url; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/evidence/Data.java b/src/main/java/org/cyclonedx/model/attestation/evidence/Data.java new file mode 100644 index 0000000000..b9b29116f2 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/evidence/Data.java @@ -0,0 +1,77 @@ +package org.cyclonedx.model.attestation.evidence; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.component.modelCard.data.Governance; +import org.cyclonedx.util.deserializer.StringListDeserializer; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "name", + "contents", + "classification", + "sensitiveData", + "governance" +}) +public class Data +{ + private String name; + + private Contents contents; + + private String classification; + + private List sensitiveData; + + private Governance governance; + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + + public Contents getContents() { + return contents; + } + + public void setContents(final Contents contents) { + this.contents = contents; + } + + @JacksonXmlElementWrapper(useWrapping = false) + @JacksonXmlProperty(localName = "sensitiveData") + public List getSensitiveData() { + return sensitiveData; + } + + public void setSensitiveData(final List sensitiveData) { + this.sensitiveData = sensitiveData; + } + + public Governance getGovernance() { + return governance; + } + + public void setGovernance(final Governance governance) { + this.governance = governance; + } + + public String getClassification() { + return classification; + } + + public void setClassification(final String classification) { + this.classification = classification; + } +} diff --git a/src/main/java/org/cyclonedx/model/attestation/evidence/Evidence.java b/src/main/java/org/cyclonedx/model/attestation/evidence/Evidence.java new file mode 100644 index 0000000000..9d21610a92 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/attestation/evidence/Evidence.java @@ -0,0 +1,128 @@ +package org.cyclonedx.model.attestation.evidence; + +import java.util.Date; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.OrganizationalContact; +import org.cyclonedx.model.Signature; +import org.cyclonedx.util.serializer.CustomDateSerializer; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "type", + "description", + "data", + "created", + "expires", + "author", + "reviewer", + "signature" +}) +public class Evidence +{ + @JacksonXmlProperty(isAttribute = true, localName = "bom-ref") + @JsonProperty("bom-ref") + private String bomRef; + + private String type; + + private String description; + + private List data; + + @JsonSerialize(using = CustomDateSerializer.class) + private Date created; + + @JsonSerialize(using = CustomDateSerializer.class) + private Date expires; + + private OrganizationalContact author; + + private OrganizationalContact reviewer; + + private Signature signature; + + public String getBomRef() { + return bomRef; + } + + public void setBomRef(final String bomRef) { + this.bomRef = bomRef; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + @JacksonXmlElementWrapper(useWrapping = false) + @JacksonXmlProperty(localName = "data") + //@JsonDeserialize(using = DataDeserializer.class) + @JsonProperty("data") + public List getData() { + return data; + } + + public void setData(final List data) { + this.data = data; + } + + public Date getCreated() { + return created; + } + + public void setCreated(final Date created) { + this.created = created; + } + + public Date getExpires() { + return expires; + } + + public void setExpires(final Date expires) { + this.expires = expires; + } + + public OrganizationalContact getAuthor() { + return author; + } + + public void setAuthor(final OrganizationalContact author) { + this.author = author; + } + + public OrganizationalContact getReviewer() { + return reviewer; + } + + public void setReviewer(final OrganizationalContact reviewer) { + this.reviewer = reviewer; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + } +} diff --git a/src/main/java/org/cyclonedx/model/definition/Definition.java b/src/main/java/org/cyclonedx/model/definition/Definition.java new file mode 100644 index 0000000000..d38edb3bf7 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/definition/Definition.java @@ -0,0 +1,30 @@ +package org.cyclonedx.model.definition; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "standards" +}) +public class Definition +{ + private List standards; + + @JacksonXmlElementWrapper(localName = "standards") + @JacksonXmlProperty(localName = "standard") + public List getStandards() { + return standards; + } + + public void setStandards(final List standards) { + this.standards = standards; + } +} diff --git a/src/main/java/org/cyclonedx/model/definition/Level.java b/src/main/java/org/cyclonedx/model/definition/Level.java new file mode 100644 index 0000000000..75eb10988b --- /dev/null +++ b/src/main/java/org/cyclonedx/model/definition/Level.java @@ -0,0 +1,76 @@ +package org.cyclonedx.model.definition; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "identifier", + "title", + "text", + "description", + "requirements" +}) +public class Level +{ + @JacksonXmlProperty(isAttribute = true, localName = "bom-ref") + @JsonProperty("bom-ref") + private String bomRef; + + private String identifier; + + private String title; + + private String description; + + private List requirements; + + public String getBomRef() { + return bomRef; + } + + public void setBomRef(final String bomRef) { + this.bomRef = bomRef; + } + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(final String identifier) { + this.identifier = identifier; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + @JacksonXmlElementWrapper(localName = "requirements") + @JacksonXmlProperty(localName = "requirement") + public List getRequirements() { + return requirements; + } + + public void setRequirements(final List requirements) { + this.requirements = requirements; + } +} diff --git a/src/main/java/org/cyclonedx/model/definition/Requirement.java b/src/main/java/org/cyclonedx/model/definition/Requirement.java new file mode 100644 index 0000000000..2b70b27e4a --- /dev/null +++ b/src/main/java/org/cyclonedx/model/definition/Requirement.java @@ -0,0 +1,128 @@ +package org.cyclonedx.model.definition; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.ExternalReference; +import org.cyclonedx.model.Property; +import org.cyclonedx.util.deserializer.StringListDeserializer; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "identifier", + "title", + "text", + "descriptions", + "openCre", + "parent", + "properties", + "externalReferences" +}) +public class Requirement +{ + @JacksonXmlProperty(isAttribute = true, localName = "bom-ref") + @JsonProperty("bom-ref") + private String bomRef; + private String identifier; + + private String title; + + private String text; + + private List descriptions; + + private List openCre; + + private String parent; + + private List properties; + + private List externalReferences; + + public String getBomRef() { + return bomRef; + } + + public void setBomRef(final String bomRef) { + this.bomRef = bomRef; + } + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(final String identifier) { + this.identifier = identifier; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getText() { + return text; + } + + public void setText(final String text) { + this.text = text; + } + + @JacksonXmlElementWrapper(localName = "descriptions") + @JacksonXmlProperty(localName = "description") + public List getDescriptions() { + return descriptions; + } + + public void setDescriptions(final List descriptions) { + this.descriptions = descriptions; + } + + @JacksonXmlElementWrapper(useWrapping = false) + @JacksonXmlProperty(localName = "openCre") + public List getOpenCre() { + return openCre; + } + + public void setOpenCre(final List openCre) { + this.openCre = openCre; + } + + public String getParent() { + return parent; + } + + public void setParent(final String parent) { + this.parent = parent; + } + + @JacksonXmlElementWrapper(localName = "properties") + @JacksonXmlProperty(localName = "property") + public List getProperties() { + return properties; + } + + public void setProperties(final List properties) { + this.properties = properties; + } + + @JacksonXmlElementWrapper(localName = "externalReferences") + @JacksonXmlProperty(localName = "externalReference") + public List getExternalReferences() { + return externalReferences; + } + + public void setExternalReferences(final List externalReferences) { + this.externalReferences = externalReferences; + } +} diff --git a/src/main/java/org/cyclonedx/model/definition/Standard.java b/src/main/java/org/cyclonedx/model/definition/Standard.java new file mode 100644 index 0000000000..83f15e20dc --- /dev/null +++ b/src/main/java/org/cyclonedx/model/definition/Standard.java @@ -0,0 +1,121 @@ +package org.cyclonedx.model.definition; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.model.ExternalReference; +import org.cyclonedx.model.Signature; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonPropertyOrder({ + "name", + "version", + "description", + "owner", + "requirements", + "levels", + "externalReferences", + "signature" +}) +public class Standard +{ + @JacksonXmlProperty(isAttribute = true, localName = "bom-ref") + @JsonProperty("bom-ref") + private String bomRef; + + private String name; + + private String version; + + private String description; + + private String owner; + + private List requirements; + + private List levels; + + private List externalReferences; + + private Signature signature; + + public String getBomRef() { + return bomRef; + } + + public void setBomRef(final String bomRef) { + this.bomRef = bomRef; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(final String version) { + this.version = version; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public String getOwner() { + return owner; + } + + public void setOwner(final String owner) { + this.owner = owner; + } + + @JacksonXmlElementWrapper(localName = "requirements") + @JacksonXmlProperty(localName = "requirement") + public List getRequirements() { + return requirements; + } + + public void setRequirements(final List requirements) { + this.requirements = requirements; + } + + public List getLevels() { + return levels; + } + + public void setLevels(final List levels) { + this.levels = levels; + } + + public List getExternalReferences() { + return externalReferences; + } + + public void setExternalReferences(final List externalReferences) { + this.externalReferences = externalReferences; + } + + public Signature getSignature() { + return signature; + } + + public void setSignature(final Signature signature) { + this.signature = signature; + } +} diff --git a/src/main/java/org/cyclonedx/util/deserializer/SignatoryDeserializer.java b/src/main/java/org/cyclonedx/util/deserializer/SignatoryDeserializer.java new file mode 100644 index 0000000000..db31c47036 --- /dev/null +++ b/src/main/java/org/cyclonedx/util/deserializer/SignatoryDeserializer.java @@ -0,0 +1,73 @@ +/* + * This file is part of CycloneDX Core (Java). + * + * 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.cyclonedx.util.deserializer; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.cyclonedx.model.ExternalReference; +import org.cyclonedx.model.OrganizationalEntity; +import org.cyclonedx.model.Signature; +import org.cyclonedx.model.attestation.affirmation.Signatory; + +public class SignatoryDeserializer + extends JsonDeserializer +{ + private final ObjectMapper mapper = new ObjectMapper(); + @Override + public Signatory deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException + { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + + Signatory signatory = new Signatory(); + + if (node.has("name")) { + signatory.setName(node.get("name").asText()); + } + + if (node.has("role")) { + signatory.setRole(node.get("role").asText()); + } + + JsonNode signatureNode = node.get("signature"); + if (signatureNode != null) { + Signature signature = mapper.convertValue(node.get("signature"), Signature.class); + signatory.setSignature(signature); + return signatory; + } + else { + // Both Organization and external references are mandatory + JsonNode organizationNode = node.get("organization"); + JsonNode externalReferenceNode = node.get("externalReference"); + + if (organizationNode != null && externalReferenceNode != null) { + OrganizationalEntity organization = mapper.convertValue(organizationNode, OrganizationalEntity.class); + ExternalReference externalReference = mapper.convertValue(externalReferenceNode, ExternalReference.class); + signatory.setExternalReferenceAndOrganization(externalReference, organization); + return signatory; + } + } + return null; + } +} diff --git a/src/main/java/org/cyclonedx/util/deserializer/StringListDeserializer.java b/src/main/java/org/cyclonedx/util/deserializer/StringListDeserializer.java index 73f9be63b2..1ed48fb518 100644 --- a/src/main/java/org/cyclonedx/util/deserializer/StringListDeserializer.java +++ b/src/main/java/org/cyclonedx/util/deserializer/StringListDeserializer.java @@ -19,9 +19,6 @@ public List deserialize(JsonParser p, DeserializationContext ctxt) throw if (p.getCurrentName().equalsIgnoreCase("aliases")) { return deserializeList(node, "alias"); } - else if (p.getCurrentName().equalsIgnoreCase("tags")) { - return deserializeList(node, "tag"); - } else if (p.getCurrentName().equalsIgnoreCase("endpoints")) { return deserializeList(node, "endpoint"); } diff --git a/src/main/java/org/cyclonedx/util/serializer/EvidenceSerializer.java b/src/main/java/org/cyclonedx/util/serializer/EvidenceSerializer.java index 34fe88e8aa..0f8d16a8eb 100644 --- a/src/main/java/org/cyclonedx/util/serializer/EvidenceSerializer.java +++ b/src/main/java/org/cyclonedx/util/serializer/EvidenceSerializer.java @@ -42,27 +42,28 @@ public void serialize(Evidence value, JsonGenerator jsonGenerator, SerializerPro private void serializeJson(final JsonGenerator gen, final Evidence evidence, SerializerProvider serializerProvider) throws IOException { gen.writeStartObject(); if (CollectionUtils.isNotEmpty(evidence.getIdentities())) { - if(version.getVersion()>=Version.VERSION_16.getVersion()) { - gen.writeObjectField("identity", evidence.getIdentities()); - } else { - gen.writeObjectField("identity", evidence.getIdentities().get(0)); - } + if (version.getVersion() >= Version.VERSION_16.getVersion()) { + gen.writeObjectField("identity", evidence.getIdentities()); + } + else { + gen.writeObjectField("identity", evidence.getIdentities().get(0)); + } } - if(CollectionUtils.isNotEmpty(evidence.getOccurrences())) { + if (CollectionUtils.isNotEmpty(evidence.getOccurrences())) { gen.writeObjectField("occurrences", evidence.getOccurrences()); } - if(evidence.getCallstack()!=null) { + if (evidence.getCallstack() != null) { gen.writeObjectField("callstack", evidence.getCallstack()); } - if(evidence.getLicenseChoice() != null) { + if (evidence.getLicenseChoice() != null) { gen.writeFieldName("licenses"); new LicenseChoiceSerializer().serialize(evidence.getLicenseChoice(), gen, serializerProvider); } - if(CollectionUtils.isNotEmpty(evidence.getCopyright())) { + if (CollectionUtils.isNotEmpty(evidence.getCopyright())) { gen.writeFieldName("copyright"); gen.writeStartArray(); for (Copyright item : evidence.getCopyright()) { diff --git a/src/main/java/org/cyclonedx/util/serializer/SignatorySerializer.java b/src/main/java/org/cyclonedx/util/serializer/SignatorySerializer.java new file mode 100644 index 0000000000..544231d87c --- /dev/null +++ b/src/main/java/org/cyclonedx/util/serializer/SignatorySerializer.java @@ -0,0 +1,66 @@ +package org.cyclonedx.util.serializer; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +import org.apache.commons.lang3.StringUtils; +import org.cyclonedx.model.attestation.affirmation.Signatory; + +public class SignatorySerializer + extends StdSerializer +{ + private final boolean isXml; + + public SignatorySerializer(boolean isXml) { + this(null, isXml); + } + + public SignatorySerializer(Class t, boolean isXml) { + super(t); + this.isXml = isXml; + } + + @Override + public void serialize(Signatory value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { + if (isXml && jsonGenerator instanceof ToXmlGenerator) { + ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator; + serializeJson(xmlGenerator, value); + } else { + serializeJson(jsonGenerator, value); + } + } + + private void serializeJson(final JsonGenerator gen, final Signatory signatory) + throws IOException + { + gen.writeStartObject(); + + if (StringUtils.isNotBlank(signatory.getName())) { + gen.writeStringField("name", signatory.getName()); + } + + if (StringUtils.isNotBlank(signatory.getRole())) { + gen.writeStringField("role", signatory.getRole()); + } + + if (signatory.getSignature() != null) { + gen.writeObjectField("signature", signatory.getSignature()); + } + else { + if (signatory.getExternalReference() != null && signatory.getOrganization() != null) { + gen.writeObjectField("organization", signatory.getOrganization()); + gen.writeObjectField("externalReference", signatory.getExternalReference()); + } + } + gen.writeEndObject(); + } + + @Override + public Class handledType() { + return Signatory.class; + } +}