Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/ci/parsers/sbom/cyclonedx.rb')
-rw-r--r--lib/gitlab/ci/parsers/sbom/cyclonedx.rb79
1 files changed, 79 insertions, 0 deletions
diff --git a/lib/gitlab/ci/parsers/sbom/cyclonedx.rb b/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
new file mode 100644
index 00000000000..deb20a2138c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Sbom
+ class Cyclonedx
+ SUPPORTED_SPEC_VERSIONS = %w[1.4].freeze
+ COMPONENT_ATTRIBUTES = %w[type name version].freeze
+
+ def parse!(blob, sbom_report)
+ @report = sbom_report
+ @data = Gitlab::Json.parse(blob)
+
+ return unless valid?
+
+ parse_report
+ rescue JSON::ParserError => e
+ report.add_error("Report JSON is invalid: #{e}")
+ end
+
+ private
+
+ attr_reader :json_data, :report, :data
+
+ def schema_validator
+ @schema_validator ||= Validators::CyclonedxSchemaValidator.new(data)
+ end
+
+ def valid?
+ valid_schema? && supported_spec_version?
+ end
+
+ def supported_spec_version?
+ return true if SUPPORTED_SPEC_VERSIONS.include?(data['specVersion'])
+
+ report.add_error(
+ "Unsupported CycloneDX spec version. Must be one of: %{versions}" \
+ % { versions: SUPPORTED_SPEC_VERSIONS.join(', ') }
+ )
+
+ false
+ end
+
+ def valid_schema?
+ return true if schema_validator.valid?
+
+ schema_validator.errors.each { |error| report.add_error(error) }
+
+ false
+ end
+
+ def parse_report
+ parse_metadata_properties
+ parse_components
+ end
+
+ def parse_metadata_properties
+ properties = data.dig('metadata', 'properties')
+ source = CyclonedxProperties.parse_source(properties)
+ report.set_source(source) if source
+ end
+
+ def parse_components
+ data['components']&.each do |component|
+ next unless supported_component_type?(component['type'])
+
+ report.add_component(component.slice(*COMPONENT_ATTRIBUTES))
+ end
+ end
+
+ def supported_component_type?(type)
+ ::Enums::Sbom.component_types.include?(type.to_sym)
+ end
+ end
+ end
+ end
+ end
+end