From a056d526b35d31755f610d15baa3fa2017600f22 Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Mon, 14 Oct 2024 19:25:43 -0500 Subject: [PATCH 1/6] #69 Add an `evidence` element to the bom_builder output. Update unit tests to match. Signed-off-by: Kyle Hammond --- lib/cyclonedx/cocoapods/bom_builder.rb | 39 ++++-- spec/cyclonedx/cocoapods/bom_builder_spec.rb | 140 ++++++++++++++++++- 2 files changed, 165 insertions(+), 14 deletions(-) diff --git a/lib/cyclonedx/cocoapods/bom_builder.rb b/lib/cyclonedx/cocoapods/bom_builder.rb index 7e7720f..3d91fbb 100644 --- a/lib/cyclonedx/cocoapods/bom_builder.rb +++ b/lib/cyclonedx/cocoapods/bom_builder.rb @@ -104,10 +104,26 @@ def xml_add_homepage(xml) end end - def add_to_bom(xml, trim_strings_length = 0) + # Add evidence of the purl identity. + # See https://github.com/CycloneDX/guides/blob/main/SBOM/en/0x60-Evidence.md for more info + def xml_add_evidence(xml, manifest_path) + xml.evidence do + xml.identity do + xml.field 'purl' + xml.confidence '0.6' + xml.methods_ do + xml.technique 'manifest-analysis' + xml.confidence '0.6' + xml.value manifest_path + end + end + end + end + + def add_to_bom(xml, manifest_path, trim_strings_length = 0) xml.component(type: 'library', 'bom-ref': purl) do xml_add_author(xml, trim_strings_length) - xml.name name + xml.name_ name xml.version version.to_s xml.description { xml.cdata description } unless description.nil? unless checksum.nil? @@ -126,6 +142,8 @@ def add_to_bom(xml, trim_strings_length = 0) xml.purl purl.slice(0, trim_strings_length) end xml_add_homepage(xml) + + xml_add_evidence(xml, manifest_path) end end @@ -133,7 +151,7 @@ class License def add_to_bom(xml) xml.license do xml.id identifier if identifier_type == :id - xml.name identifier if identifier_type == :name + xml.name_ identifier if identifier_type == :name xml.text_ text unless text.nil? xml.url url unless url.nil? end @@ -145,7 +163,7 @@ class Component def add_to_bom(xml) xml.component(type: type, 'bom-ref': bomref) do xml.group group unless group.nil? - xml.name name + xml.name_ name xml.version version end end @@ -154,10 +172,11 @@ def add_to_bom(xml) class BOMBuilder NAMESPACE = 'http://cyclonedx.org/schema/bom/1.5' - attr_reader :component, :pods, :dependencies + attr_reader :component, :pods, :manifest_path, :dependencies - def initialize(pods:, component: nil, dependencies: nil) + def initialize(pods:, manifest_path:, component: nil, dependencies: nil) @pods = pods.sort_by(&:purl) + @manifest_path = manifest_path @component = component @dependencies = dependencies&.sort end @@ -184,17 +203,17 @@ def unchecked_bom(version: 1, trim_strings_length: 0) xml.bom(xmlns: NAMESPACE, version: version.to_i.to_s, serialNumber: "urn:uuid:#{SecureRandom.uuid}") do bom_metadata(xml) - bom_components(xml, pods, trim_strings_length) + bom_components(xml, pods, manifest_path, trim_strings_length) bom_dependencies(xml, dependencies) end end.to_xml end - def bom_components(xml, pods, trim_strings_length) + def bom_components(xml, pods, manifest_path, trim_strings_length) xml.components do pods.each do |pod| - pod.add_to_bom(xml, trim_strings_length) + pod.add_to_bom(xml, manifest_path, trim_strings_length) end end end @@ -223,7 +242,7 @@ def bom_tools(xml) xml.tools do xml.tool do xml.vendor 'CycloneDX' - xml.name 'cyclonedx-cocoapods' + xml.name_ 'cyclonedx-cocoapods' xml.version VERSION end end diff --git a/spec/cyclonedx/cocoapods/bom_builder_spec.rb b/spec/cyclonedx/cocoapods/bom_builder_spec.rb index e7dd824..7474e42 100644 --- a/spec/cyclonedx/cocoapods/bom_builder_spec.rb +++ b/spec/cyclonedx/cocoapods/bom_builder_spec.rb @@ -38,13 +38,13 @@ let(:pod) { described_class.new(name: pod_name, version: pod_version, checksum: checksum) } let(:xml) do Nokogiri::XML(Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml| - pod.add_to_bom(xml) + pod.add_to_bom(xml, 'unused.lock') end.to_xml) end let(:shortXML) do Nokogiri::XML(Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml| - pod.add_to_bom(xml, 7) + pod.add_to_bom(xml, 'unused.lock', 7) end.to_xml) end @@ -330,6 +330,17 @@ Alamofire 5.6.2 pkg:cocoapods/Alamofire@5.6.2 + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewbacca @@ -337,6 +348,17 @@ FirebaseAnalytics 7.10.0 pkg:cocoapods/FirebaseAnalytics@7.10.0 + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewbacca @@ -344,6 +366,17 @@ MSAL 1.2.1 pkg:cocoapods/MSAL@1.2.1 + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewbacca @@ -351,6 +384,17 @@ MSAL/app-lib 1.2.1 pkg:cocoapods/MSAL@1.2.1#app-lib + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewbacca @@ -358,6 +402,17 @@ Realm 5.5.1 pkg:cocoapods/Realm@5.5.1 + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewbacca @@ -365,6 +420,17 @@ RxSwift 5.1.2 pkg:cocoapods/RxSwift@5.1.2 + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + XML @@ -379,6 +445,17 @@ Alamofire 5.6.2 pkg:co + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewba @@ -386,6 +463,17 @@ FirebaseAnalytics 7.10.0 pkg:co + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewba @@ -393,6 +481,17 @@ MSAL 1.2.1 pkg:co + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewba @@ -400,6 +499,17 @@ MSAL/app-lib 1.2.1 pkg:co + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewba @@ -407,6 +517,17 @@ Realm 5.5.1 pkg:co + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + Chewba @@ -414,6 +535,17 @@ RxSwift 5.1.2 pkg:co + + + purl + 0.6 + + manifest-analysis + 0.6 + sample_manifest.lock + + + XML @@ -552,7 +684,7 @@ end context 'without a component' do - let(:bom_builder) { described_class.new(pods: pods) } + let(:bom_builder) { described_class.new(pods: pods, manifest_path: 'sample_manifest.lock') } let(:dependencies_result) { '' } it_behaves_like 'bom_generator' @@ -562,7 +694,7 @@ let(:component) do CycloneDX::CocoaPods::Component.new(name: 'Application', version: '1.3.5', type: 'application') end - let(:bom_builder) { described_class.new(component: component, pods: pods, dependencies: dependencies) } + let(:bom_builder) { described_class.new(component: component, manifest_path: 'sample_manifest.lock', pods: pods, dependencies: dependencies) } # Important: these expected dependencies are sorted alphabetically let(:dependencies_result) do <<~XML From 441db4c7f44edbd9e80da0d6a0a923171c5b3bde Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Mon, 14 Oct 2024 22:40:33 -0500 Subject: [PATCH 2/6] Fixes #69. Added `method` container in the bom evidence section, and hooked up the CLI runner to pass the proper manifest file path for evidence. Signed-off-by: Kyle Hammond --- lib/cyclonedx/cocoapods/bom_builder.rb | 8 +- lib/cyclonedx/cocoapods/cli_runner.rb | 17 ++- spec/cyclonedx/cocoapods/bom_builder_spec.rb | 103 ++++++++++++------- 3 files changed, 83 insertions(+), 45 deletions(-) diff --git a/lib/cyclonedx/cocoapods/bom_builder.rb b/lib/cyclonedx/cocoapods/bom_builder.rb index 3d91fbb..d4db436 100644 --- a/lib/cyclonedx/cocoapods/bom_builder.rb +++ b/lib/cyclonedx/cocoapods/bom_builder.rb @@ -112,9 +112,11 @@ def xml_add_evidence(xml, manifest_path) xml.field 'purl' xml.confidence '0.6' xml.methods_ do - xml.technique 'manifest-analysis' - xml.confidence '0.6' - xml.value manifest_path + xml.method_ do + xml.technique 'manifest-analysis' + xml.confidence '0.6' + xml.value manifest_path + end end end end diff --git a/lib/cyclonedx/cocoapods/cli_runner.rb b/lib/cyclonedx/cocoapods/cli_runner.rb index 7c8cb2f..12973ad 100644 --- a/lib/cyclonedx/cocoapods/cli_runner.rb +++ b/lib/cyclonedx/cocoapods/cli_runner.rb @@ -39,9 +39,9 @@ def run setup_logger(verbose: options[:verbose]) @logger.debug "Running cyclonedx-cocoapods with options: #{options}" - component, pods, dependencies = analyze(options) + component, pods, manifest_path, dependencies = analyze(options) - build_and_write_bom(options, component, pods, dependencies) + build_and_write_bom(options, component, pods, manifest_path, dependencies) rescue StandardError => e @logger.error ([e.message] + e.backtrace).join($INPUT_RECORD_SEPARATOR) exit 1 @@ -144,11 +144,18 @@ def analyze(options) dependencies[component.bomref] = top_deps end - [component, pods, dependencies] + manifest_path = lockfile.defined_in_file + if manifest_path.absolute? + # Use the folder that we are building in, then the path to the manifest file + manifest_path = Pathname.pwd.basename + manifest_path.relative_path_from(Pathname.pwd) + end + + [component, pods, manifest_path, dependencies] end - def build_and_write_bom(options, component, pods, dependencies) - builder = BOMBuilder.new(pods: pods, component: component, dependencies: dependencies) + def build_and_write_bom(options, component, pods, manifest_path, dependencies) + builder = BOMBuilder.new(pods: pods, manifest_path: manifest_path, + component: component, dependencies: dependencies) bom = builder.bom(version: options[:bom_version] || 1, trim_strings_length: options[:trim_strings_length] || 0) write_bom_to_file(bom: bom, options: options) diff --git a/spec/cyclonedx/cocoapods/bom_builder_spec.rb b/spec/cyclonedx/cocoapods/bom_builder_spec.rb index 7474e42..3340e56 100644 --- a/spec/cyclonedx/cocoapods/bom_builder_spec.rb +++ b/spec/cyclonedx/cocoapods/bom_builder_spec.rb @@ -335,9 +335,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -353,9 +355,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -371,9 +375,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -389,9 +395,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -407,9 +415,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -425,9 +435,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -450,9 +462,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -468,9 +482,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -486,9 +502,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -504,9 +522,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -522,9 +542,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -540,9 +562,11 @@ purl 0.6 - manifest-analysis - 0.6 - sample_manifest.lock + + manifest-analysis + 0.6 + sample_manifest.lock + @@ -694,7 +718,12 @@ let(:component) do CycloneDX::CocoaPods::Component.new(name: 'Application', version: '1.3.5', type: 'application') end - let(:bom_builder) { described_class.new(component: component, manifest_path: 'sample_manifest.lock', pods: pods, dependencies: dependencies) } + let(:bom_builder) do + described_class.new(component: component, + manifest_path: 'sample_manifest.lock', + pods: pods, + dependencies: dependencies) + end # Important: these expected dependencies are sorted alphabetically let(:dependencies_result) do <<~XML From 590bc6e8e9355382f77f9ac55888c37ccd7e4465 Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Mon, 14 Oct 2024 22:45:32 -0500 Subject: [PATCH 3/6] Updated version number to 1.4.0. Updated example_bom.xml file. Signed-off-by: Kyle Hammond --- CHANGELOG.md | 5 ++- cyclonedx-cocoapods.gemspec | 4 +- example_bom.xml | 65 ++++++++++++++++++++++++++++-- lib/cyclonedx/cocoapods/version.rb | 2 +- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd01f1e..f421b82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [1.4.0] + +### Added +- Added `evidence` element to the component output to indicate that we are doing manifest analisys to generate the bom. ([Issue #69](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/69)) [@macblazer](https://github.com/macblazer). ### Fixed - Properly concatenate paths to Podfile and Podfile.lock (with unit tests!). ([Issue #71](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/71)) [@macblazer](https://github.com/macblazer). diff --git a/cyclonedx-cocoapods.gemspec b/cyclonedx-cocoapods.gemspec index 864eee2..832d9d4 100644 --- a/cyclonedx-cocoapods.gemspec +++ b/cyclonedx-cocoapods.gemspec @@ -26,8 +26,8 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] - spec.add_runtime_dependency 'cocoapods', ['>= 1.10.1', '< 2.0'] - spec.add_runtime_dependency 'nokogiri', ['>= 1.11.2', '< 2.0'] + spec.add_dependency 'cocoapods', ['>= 1.10.1', '< 2.0'] + spec.add_dependency 'nokogiri', ['>= 1.11.2', '< 2.0'] spec.add_development_dependency 'equivalent-xml', '~> 0.6.0' spec.add_development_dependency 'rake', '~> 13.0' diff --git a/example_bom.xml b/example_bom.xml index b62e5ef..dd4edc0 100644 --- a/example_bom.xml +++ b/example_bom.xml @@ -1,15 +1,15 @@ - + - 2024-02-08T06:35:59Z + 2024-10-15T03:43:07Z CycloneDX cyclonedx-cocoapods - 1.3.0 + 1.4.0 - + kizitonwose/PodsUpdater 1.0.3 @@ -35,6 +35,19 @@ http://github.com/raspu/Highlightr + + + purl + 0.6 + + + manifest-analysis + 0.6 + PodsUpdater/Podfile.lock + + + + Krunoslav Zaher <krunoslav.zaher@gmail.com> @@ -56,6 +69,19 @@ https://github.com/ReactiveX/RxSwift + + + purl + 0.6 + + + manifest-analysis + 0.6 + PodsUpdater/Podfile.lock + + + + Krunoslav Zaher <krunoslav.zaher@gmail.com> @@ -79,6 +105,19 @@ https://github.com/ReactiveX/RxSwift + + + purl + 0.6 + + + manifest-analysis + 0.6 + PodsUpdater/Podfile.lock + + + + Krunoslav Zaher <krunoslav.zaher@gmail.com> @@ -110,9 +149,27 @@ git diff | grep bug | less # linux pipes - programs communicate by sen https://github.com/ReactiveX/RxSwift + + + purl + 0.6 + + + manifest-analysis + 0.6 + PodsUpdater/Podfile.lock + + + + + + + + + diff --git a/lib/cyclonedx/cocoapods/version.rb b/lib/cyclonedx/cocoapods/version.rb index db2d56e..46dfd7c 100644 --- a/lib/cyclonedx/cocoapods/version.rb +++ b/lib/cyclonedx/cocoapods/version.rb @@ -21,6 +21,6 @@ module CycloneDX module CocoaPods - VERSION = '1.3.0' + VERSION = '1.4.0' end end From 98a0013d4d033131550b44ae805ede421035232c Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Mon, 14 Oct 2024 23:04:04 -0500 Subject: [PATCH 4/6] Keep Rubocop happy. Signed-off-by: Kyle Hammond --- .rubocop.yml | 2 +- lib/cyclonedx/cocoapods/bom_builder.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index f851cda..d4610b9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -35,7 +35,7 @@ Metrics/BlockLength: # Allow some long methods because breaking them up doesn't help anything. Metrics/MethodLength: - AllowedMethods: ['parse_options', 'add_to_bom', 'append_all_pod_dependencies'] + AllowedMethods: ['parse_options', 'add_to_bom', 'append_all_pod_dependencies', 'xml_add_evidence'] Metrics/AbcSize: AllowedMethods: ['parse_options', 'add_to_bom', 'source_for_pod'] diff --git a/lib/cyclonedx/cocoapods/bom_builder.rb b/lib/cyclonedx/cocoapods/bom_builder.rb index d4db436..57152f2 100644 --- a/lib/cyclonedx/cocoapods/bom_builder.rb +++ b/lib/cyclonedx/cocoapods/bom_builder.rb @@ -171,6 +171,7 @@ def add_to_bom(xml) end end + # Turns the internal model data into an XML bom. class BOMBuilder NAMESPACE = 'http://cyclonedx.org/schema/bom/1.5' From 30474ec151a86e4ae40812797d0c5828e2fd5a04 Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Mon, 14 Oct 2024 23:15:59 -0500 Subject: [PATCH 5/6] Added note in the CHANGELOG about a PR that fixed an issue. Also updated the license check to the latest apache/skywalking-eyes release. Signed-off-by: Kyle Hammond --- .github/workflows/ruby.yml | 2 +- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index b6b3430..edf18a3 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -36,7 +36,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4 - name: Check license headers - uses: apache/skywalking-eyes@v0.4.0 + uses: apache/skywalking-eyes@v0.6.0 with: config: .licenserc.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index f421b82..d3c1298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `evidence` element to the component output to indicate that we are doing manifest analisys to generate the bom. ([Issue #69](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/69)) [@macblazer](https://github.com/macblazer). ### Fixed +- Added top level dependencies when the metadata/component is specified (by using the `--name`, `--version`, and `--type` parameters). ([PR #70](https://github.com/CycloneDX/cyclonedx-cocoapods/pull/70)) [@fnxpt](https://github.com/fnxpt) - Properly concatenate paths to Podfile and Podfile.lock (with unit tests!). ([Issue #71](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/71)) [@macblazer](https://github.com/macblazer). ## [1.3.0] From 9fe3cc41b3cb772eaf3d22431bd980b468500351 Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Mon, 14 Oct 2024 23:25:48 -0500 Subject: [PATCH 6/6] Fix a spelling error. Signed-off-by: Kyle Hammond --- .github/workflows/ruby.yml | 2 +- CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index edf18a3..b6b3430 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -36,7 +36,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4 - name: Check license headers - uses: apache/skywalking-eyes@v0.6.0 + uses: apache/skywalking-eyes@v0.4.0 with: config: .licenserc.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index d3c1298..62a12fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.4.0] ### Added -- Added `evidence` element to the component output to indicate that we are doing manifest analisys to generate the bom. ([Issue #69](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/69)) [@macblazer](https://github.com/macblazer). +- Added `evidence` element to the component output to indicate that we are doing manifest analysis to generate the bom. ([Issue #69](https://github.com/CycloneDX/cyclonedx-cocoapods/issues/69)) [@macblazer](https://github.com/macblazer). ### Fixed - Added top level dependencies when the metadata/component is specified (by using the `--name`, `--version`, and `--type` parameters). ([PR #70](https://github.com/CycloneDX/cyclonedx-cocoapods/pull/70)) [@fnxpt](https://github.com/fnxpt)