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

cyclonedx.rb « sbom « parsers « ci « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: aa594ca4049a2229d128f1a5b78a862e9406dc35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# frozen_string_literal: true

module Gitlab
  module Ci
    module Parsers
      module Sbom
        class Cyclonedx
          SUPPORTED_SPEC_VERSIONS = %w[1.4].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_data|
              type = component_data['type']
              next unless supported_component_type?(type)

              component = ::Gitlab::Ci::Reports::Sbom::Component.new(
                type: type,
                name: component_data['name'],
                version: component_data['version']
              )

              report.add_component(component)
            end
          end

          def supported_component_type?(type)
            ::Enums::Sbom.component_types.include?(type.to_sym)
          end
        end
      end
    end
  end
end