mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 13:51:33 -06:00
Adds definitions for representing software bill of materials (SBOM) information and generating SPDX SBOMs. Issue: #26719 Issue: #27001
521 lines
16 KiB
C++
521 lines
16 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#include "cmSpdx.h"
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include "cmSbomSerializer.h"
|
|
|
|
inline void SerializeIfPresent(cmSbomSerializer& s, std::string const& key,
|
|
cm::optional<std::string> const& v)
|
|
{
|
|
if (v) {
|
|
s.AddString(key, *v);
|
|
}
|
|
}
|
|
|
|
std::string to_string(cmSpdxIntegrityMethod::HashAlgorithmId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::ADLER32:
|
|
return "ADLER32";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B256:
|
|
return "BLAKE2B256";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B384:
|
|
return "BLAKE2B384";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B512:
|
|
return "BLAKE2B512";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE3:
|
|
return "BLAKE3";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::MD2:
|
|
return "MD2";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::MD4:
|
|
return "MD4";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::MD5:
|
|
return "MD5";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::MD6:
|
|
return "MD6";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA1:
|
|
return "SHA1";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA224:
|
|
return "SHA224";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA256:
|
|
return "SHA256";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA384:
|
|
return "SHA384";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA512:
|
|
return "SHA512";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_256:
|
|
return "SHA3_256";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_384:
|
|
return "SHA3_384";
|
|
case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_512:
|
|
return "SHA3_512";
|
|
}
|
|
throw std::invalid_argument("Unknown HashAlgorithmId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxSoftwareArtifact::PurposeId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxSoftwareArtifact::PurposeId::APPLICATION:
|
|
return "APPLICATION";
|
|
case cmSpdxSoftwareArtifact::PurposeId::ARCHIVE:
|
|
return "ARCHIVE";
|
|
case cmSpdxSoftwareArtifact::PurposeId::CONTAINER:
|
|
return "CONTAINER";
|
|
case cmSpdxSoftwareArtifact::PurposeId::DATA:
|
|
return "DATA";
|
|
case cmSpdxSoftwareArtifact::PurposeId::DEVICE:
|
|
return "DEVICE";
|
|
case cmSpdxSoftwareArtifact::PurposeId::FIRMWARE:
|
|
return "FIRMWARE";
|
|
case cmSpdxSoftwareArtifact::PurposeId::FILE:
|
|
return "FILE";
|
|
case cmSpdxSoftwareArtifact::PurposeId::INSTALL:
|
|
return "INSTALL";
|
|
case cmSpdxSoftwareArtifact::PurposeId::LIBRARY:
|
|
return "LIBRARY";
|
|
case cmSpdxSoftwareArtifact::PurposeId::MODULE:
|
|
return "MODULE";
|
|
case cmSpdxSoftwareArtifact::PurposeId::OPERATING_SYSTEM:
|
|
return "OPERATING_SYSTEM";
|
|
case cmSpdxSoftwareArtifact::PurposeId::SOURCE:
|
|
return "SOURCE";
|
|
}
|
|
throw std::invalid_argument("Unknown PurposeId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxSbom::TypeId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxSbom::TypeId::ANALYZED:
|
|
return "ANALYZED";
|
|
case cmSpdxSbom::TypeId::BUILD:
|
|
return "BUILD";
|
|
case cmSpdxSbom::TypeId::DEPLOYED:
|
|
return "DEPLOYED";
|
|
case cmSpdxSbom::TypeId::DESIGN:
|
|
return "DESIGN";
|
|
case cmSpdxSbom::TypeId::RUNTIME:
|
|
return "RUNTIME";
|
|
case cmSpdxSbom::TypeId::SOURCE:
|
|
return "SOURCE";
|
|
case cmSpdxSbom::TypeId::TEST:
|
|
return "TEST";
|
|
}
|
|
throw std::invalid_argument("Unknown Sbom::TypeId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxFile::FileKindId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxFile::FileKindId::DIRECTORY:
|
|
return "DIRECTORY";
|
|
case cmSpdxFile::FileKindId::FILE:
|
|
return "FILE";
|
|
}
|
|
throw std::invalid_argument("Unknown File::FileKindId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxRelationship::RelationshipTypeId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxRelationship::RelationshipTypeId::DESCRIBES:
|
|
return "DESCRIBES";
|
|
case cmSpdxRelationship::RelationshipTypeId::CONTAINS:
|
|
return "CONTAINS";
|
|
case cmSpdxRelationship::RelationshipTypeId::DEPENDS_ON:
|
|
return "DEPENDS_ON";
|
|
case cmSpdxRelationship::RelationshipTypeId::OTHER:
|
|
return "OTHER";
|
|
}
|
|
throw std::invalid_argument("Unknown RelationshipTypeId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxLifecycleScopedRelationship::ScopeId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxLifecycleScopedRelationship::ScopeId::BUILD:
|
|
return "BUILD";
|
|
case cmSpdxLifecycleScopedRelationship::ScopeId::DESIGN:
|
|
return "DESIGN";
|
|
case cmSpdxLifecycleScopedRelationship::ScopeId::RUNTIME:
|
|
return "RUNTIME";
|
|
case cmSpdxLifecycleScopedRelationship::ScopeId::TEST:
|
|
return "TEST";
|
|
}
|
|
throw std::invalid_argument("Unknown Lifecycle ScopeId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxAnnotation::AnnotationTypeId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxAnnotation::AnnotationTypeId::REVIEW:
|
|
return "REVIEW";
|
|
case cmSpdxAnnotation::AnnotationTypeId::OTHER:
|
|
return "OTHER";
|
|
}
|
|
throw std::invalid_argument("Unknown AnnotationTypeId");
|
|
}
|
|
|
|
std::string to_string(cmSpdxArtifact::SupportTypeId id)
|
|
{
|
|
switch (id) {
|
|
case cmSpdxArtifact::SupportTypeId::COMMUNITY:
|
|
return "COMMUNITY";
|
|
case cmSpdxArtifact::SupportTypeId::COMMERCIAL:
|
|
return "COMMERCIAL";
|
|
case cmSpdxArtifact::SupportTypeId::NONE:
|
|
return "NONE";
|
|
}
|
|
throw std::invalid_argument("Unknown SupportTypeId");
|
|
}
|
|
|
|
void cmSpdxExternalIdentifier::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "ExternalIdentifier");
|
|
SerializeIfPresent(serializer, "externalIdentifierType",
|
|
ExternalIdentifierType);
|
|
SerializeIfPresent(serializer, "identifier", Identifier);
|
|
SerializeIfPresent(serializer, "comment", Comment);
|
|
SerializeIfPresent(serializer, "identifierLocation", IdentifierLocation);
|
|
SerializeIfPresent(serializer, "issuingAuthority", IssuingAuthority);
|
|
}
|
|
|
|
void cmSpdxExternalRef::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "ExternalRef");
|
|
SerializeIfPresent(serializer, "externalRefType", ExternalRefType);
|
|
SerializeIfPresent(serializer, "locator", Locator);
|
|
SerializeIfPresent(serializer, "contentType", ContentType);
|
|
SerializeIfPresent(serializer, "comment", Comment);
|
|
}
|
|
|
|
void cmSpdxChecksum::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "Checksum");
|
|
serializer.AddString("algorithm", to_string(Algorithm));
|
|
serializer.AddString("checksumValue", ChecksumValue);
|
|
}
|
|
|
|
void cmSpdxCreationInfo::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "CreationInfo");
|
|
SerializeIfPresent(serializer, "@id", SpdxId);
|
|
if (SpecVersion) {
|
|
serializer.AddString("specVersion", *SpecVersion);
|
|
}
|
|
SerializeIfPresent(serializer, "comment", Comment);
|
|
SerializeIfPresent(serializer, "created", Created);
|
|
if (!CreatedBy.empty()) {
|
|
serializer.AddVectorIfPresent("createdBy", CreatedBy);
|
|
}
|
|
if (!CreatedUsing.empty()) {
|
|
serializer.AddVectorIfPresent("createdUsing", CreatedUsing);
|
|
}
|
|
}
|
|
|
|
void cmSpdxIntegrityMethod::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "IntegrityMethod");
|
|
SerializeIfPresent(serializer, "comment", Comment);
|
|
}
|
|
|
|
void cmSpdxElement::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "Element");
|
|
SerializeIfPresent(serializer, "@id", SpdxId);
|
|
SerializeIfPresent(serializer, "name", Name);
|
|
SerializeIfPresent(serializer, "summary", Summary);
|
|
SerializeIfPresent(serializer, "description", Description);
|
|
SerializeIfPresent(serializer, "comment", Comment);
|
|
if (CreationInfo) {
|
|
serializer.AddVisitable("creationInfo", *CreationInfo);
|
|
}
|
|
if (VerifiedUsing) {
|
|
serializer.AddVisitable("verifiedUsing", *VerifiedUsing);
|
|
}
|
|
if (!ExternalRef.empty()) {
|
|
serializer.AddVectorIfPresent("externalRef", ExternalRef);
|
|
}
|
|
if (!ExternalIdentifier.empty()) {
|
|
serializer.AddVectorIfPresent("externalIdentifier", ExternalIdentifier);
|
|
}
|
|
if (Extension) {
|
|
serializer.AddVisitable("extension", *Extension);
|
|
}
|
|
}
|
|
|
|
void cmSpdxTool::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "Tool");
|
|
}
|
|
|
|
void cmSpdxAgent::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "Agent");
|
|
}
|
|
|
|
void cmSpdxOrganization::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxAgent::Serialize(serializer);
|
|
serializer.AddString("type", "Organization");
|
|
}
|
|
|
|
void cmSpdxPerson::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxAgent::Serialize(serializer);
|
|
serializer.AddString("type", "Person");
|
|
}
|
|
|
|
void cmSpdxSoftwareAgent::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxAgent::Serialize(serializer);
|
|
serializer.AddString("type", "SoftwareAgent");
|
|
}
|
|
|
|
void cmSpdxPositiveIntegerRange::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "PositiveIntegerRange");
|
|
SerializeIfPresent(serializer, "beginIntegerRange", BeginIntegerRange);
|
|
SerializeIfPresent(serializer, "endIntegerRange", EndIntegerRange);
|
|
}
|
|
|
|
void cmSpdxRelationship::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "Relationship");
|
|
if (From) {
|
|
serializer.AddVisitable("from", *From);
|
|
}
|
|
if (!To.empty()) {
|
|
serializer.AddVectorIfPresent("to", To);
|
|
}
|
|
if (RelationshipType) {
|
|
serializer.AddString("relationshipType", to_string(*RelationshipType));
|
|
}
|
|
SerializeIfPresent(serializer, "startTime", StartTime);
|
|
SerializeIfPresent(serializer, "endTime", EndTime);
|
|
}
|
|
|
|
void cmSpdxLifecycleScopedRelationship::Serialize(
|
|
cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxRelationship::Serialize(serializer);
|
|
serializer.AddString("type", "LifecycleScopedRelationship");
|
|
if (Scope) {
|
|
serializer.AddString("scope", to_string(*Scope));
|
|
}
|
|
}
|
|
|
|
void cmSpdxArtifact::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "Artifact");
|
|
if (!OriginatedBy.empty()) {
|
|
serializer.AddVectorIfPresent("originatedBy", OriginatedBy);
|
|
}
|
|
if (SuppliedBy) {
|
|
serializer.AddVisitable("suppliedBy", *SuppliedBy);
|
|
}
|
|
SerializeIfPresent(serializer, "builtTime", BuiltTime);
|
|
SerializeIfPresent(serializer, "releaseTime", ReleaseTime);
|
|
SerializeIfPresent(serializer, "validUntilTime", ValidUntilTime);
|
|
SerializeIfPresent(serializer, "standardName", StandardName);
|
|
if (Support) {
|
|
serializer.AddString("support", to_string(*Support));
|
|
}
|
|
}
|
|
|
|
void cmSpdxIndividualElement::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "IndividualElement");
|
|
}
|
|
|
|
void cmSpdxAnnotation::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "Annotation");
|
|
if (AnnotationType) {
|
|
serializer.AddString("annotationType", to_string(*AnnotationType));
|
|
}
|
|
SerializeIfPresent(serializer, "contentType", ContentType);
|
|
SerializeIfPresent(serializer, "statement", Statement);
|
|
if (Element) {
|
|
serializer.AddVisitable("element", *Element);
|
|
}
|
|
}
|
|
|
|
void cmSpdxExternalMap::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "ExternalMap");
|
|
SerializeIfPresent(serializer, "externalSpdxId", ExternalSpdxId);
|
|
if (VerifiedUsing) {
|
|
serializer.AddVisitable("verifiedUsing", *VerifiedUsing);
|
|
}
|
|
SerializeIfPresent(serializer, "locationHistory", LocationHistory);
|
|
if (DefiningArtifact) {
|
|
serializer.AddVisitable("definingArtifact", *DefiningArtifact);
|
|
}
|
|
}
|
|
|
|
void cmSpdxNamespaceMap::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "NamespaceMap");
|
|
SerializeIfPresent(serializer, "prefix", Prefix);
|
|
SerializeIfPresent(serializer, "namespace", Namespace);
|
|
}
|
|
|
|
void cmSpdxElementCollection::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElement::Serialize(serializer);
|
|
serializer.AddString("type", "ElementCollection");
|
|
if (!Elements.empty()) {
|
|
serializer.AddVectorIfPresent("element", Elements);
|
|
}
|
|
if (!RootElements.empty()) {
|
|
serializer.AddVectorIfPresent("rootElement", RootElements);
|
|
}
|
|
if (!ProfileConformance.empty()) {
|
|
serializer.AddVectorIfPresent("profileConformance", ProfileConformance);
|
|
}
|
|
}
|
|
|
|
void cmSpdxPackageVerificationCode::Serialize(
|
|
cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "PackageVerificationCode");
|
|
if (Algorithm) {
|
|
serializer.AddString("algorithm", to_string(*Algorithm));
|
|
}
|
|
SerializeIfPresent(serializer, "hashValue", HashValue);
|
|
SerializeIfPresent(serializer, "packageVerificationCodeExcludedFile",
|
|
PackageVerificationCodeExcludedFile);
|
|
}
|
|
|
|
void cmSpdxHash::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString("type", "Hash");
|
|
serializer.AddString("hashAlgorithm", to_string(HashAlgorithm));
|
|
serializer.AddString("hashValue", HashValue);
|
|
}
|
|
|
|
void cmSpdxBundle::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElementCollection::Serialize(serializer);
|
|
serializer.AddString("type", "Bundle");
|
|
SerializeIfPresent(serializer, "context", Context);
|
|
}
|
|
|
|
void cmSpdxBom::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxBundle::Serialize(serializer);
|
|
serializer.AddString("type", "Bom");
|
|
}
|
|
|
|
void cmSpdxSbom::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxBom::Serialize(serializer);
|
|
serializer.AddString("type", "software_Sbom");
|
|
if (Types) {
|
|
for (auto const& t : *Types) {
|
|
serializer.AddString("sbomType", to_string(t));
|
|
}
|
|
}
|
|
if (LifecycleScope) {
|
|
serializer.AddString("lifecycleScope", to_string(*LifecycleScope));
|
|
}
|
|
}
|
|
|
|
void cmSpdxSoftwareArtifact::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxArtifact::Serialize(serializer);
|
|
serializer.AddString("type", "software_SoftwareArtifact");
|
|
if (PrimaryPurpose) {
|
|
serializer.AddString("primaryPurpose", to_string(*PrimaryPurpose));
|
|
}
|
|
if (AdditionalPurpose) {
|
|
for (auto const& p : *AdditionalPurpose) {
|
|
serializer.AddString("additionalPurpose", to_string(p));
|
|
}
|
|
}
|
|
SerializeIfPresent(serializer, "copyrightText", CopyrightText);
|
|
SerializeIfPresent(serializer, "attributionText", AttributionText);
|
|
if (ContentIdentifier) {
|
|
serializer.AddVisitable("contentIdentifier", *ContentIdentifier);
|
|
}
|
|
SerializeIfPresent(serializer, "artifactSize", ArtifactSize);
|
|
}
|
|
|
|
void cmSpdxPackage::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxSoftwareArtifact::Serialize(serializer);
|
|
serializer.AddString("type", "software_Package");
|
|
SerializeIfPresent(serializer, "downloadLocation", DownloadLocation);
|
|
SerializeIfPresent(serializer, "homePage", Homepage);
|
|
SerializeIfPresent(serializer, "packageVersion", PackageVersion);
|
|
SerializeIfPresent(serializer, "packageUrl", PackageUrl);
|
|
SerializeIfPresent(serializer, "sourceInfo", SourceInfo);
|
|
}
|
|
|
|
void cmSpdxFile::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxArtifact::Serialize(serializer);
|
|
serializer.AddString("type", "software_File");
|
|
if (ContentType) {
|
|
serializer.AddString("contentType", *ContentType);
|
|
}
|
|
if (FileType) {
|
|
serializer.AddString("fileType", to_string(*FileType));
|
|
}
|
|
}
|
|
|
|
void cmSpdxContentIdentifier::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxIntegrityMethod::Serialize(serializer);
|
|
serializer.AddString("type", "software_ContentIdentifier");
|
|
SerializeIfPresent(serializer, "contentIdentifierType",
|
|
ContentIdentifierType);
|
|
SerializeIfPresent(serializer, "contentValue", ContentValue);
|
|
}
|
|
|
|
void cmSpdxSnippet::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxSoftwareArtifact::Serialize(serializer);
|
|
serializer.AddString("type", "software_Snippet");
|
|
SerializeIfPresent(serializer, "byteRange", ByteRange);
|
|
SerializeIfPresent(serializer, "lineRange", LineRange);
|
|
if (SnippetFromFile) {
|
|
serializer.AddVisitable("snippetFromFile", *SnippetFromFile);
|
|
}
|
|
}
|
|
|
|
void cmSpdxDocument::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
cmSpdxElementCollection::Serialize(serializer);
|
|
|
|
serializer.AddString("type", "SpdxDocument");
|
|
if (ExternalMap) {
|
|
serializer.AddVisitable("externalMap", *ExternalMap);
|
|
}
|
|
if (NamespaceMap) {
|
|
serializer.AddVisitable("namespaceMap", *NamespaceMap);
|
|
}
|
|
SerializeIfPresent(serializer, "dataLicense", DataLicense);
|
|
}
|
|
|
|
void cmSbomDocument::Serialize(cmSbomSerializer& serializer) const
|
|
{
|
|
serializer.AddString(
|
|
"@context",
|
|
Context.value_or("https://spdx.org/rdf/3.0.1/spdx-context.jsonld"));
|
|
if (!Graph.empty()) {
|
|
serializer.AddVectorIfPresent("@graph", Graph);
|
|
}
|
|
}
|