Commit 9ce2bbfb authored by mo khan's avatar mo khan Committed by Nick Thomas

Check for violations using spdx identifier

* Ensure spdx id or name match checks work for v2
* Add changelog entry
parent 6f4b324b
...@@ -38,5 +38,9 @@ class SoftwareLicensePolicy < ApplicationRecord ...@@ -38,5 +38,9 @@ class SoftwareLicensePolicy < ApplicationRecord
with_license.where(SoftwareLicense.arel_table[:name].lower.in(Array(license_name).map(&:downcase))) with_license.where(SoftwareLicense.arel_table[:name].lower.in(Array(license_name).map(&:downcase)))
end end
scope :by_spdx, -> (spdx_identifier) do
with_license.where(software_licenses: { spdx_identifier: spdx_identifier })
end
delegate :name, to: :software_license delegate :name, to: :software_license
end end
---
title: Check for software license violations using SPDX identifiers
merge_request: 18300
author:
type: changed
...@@ -34,7 +34,9 @@ module Gitlab ...@@ -34,7 +34,9 @@ module Gitlab
end end
def violates?(software_license_policies) def violates?(software_license_policies)
software_license_policies.blacklisted.with_license_by_name(license_names).exists? policies_with_matching_license_name = software_license_policies.blacklisted.with_license_by_name(license_names)
policies_with_matching_spdx_id = software_license_policies.blacklisted.by_spdx(licenses.map(&:id).compact)
policies_with_matching_spdx_id.or(policies_with_matching_license_name).exists?
end end
def diff_with(other_report) def diff_with(other_report)
......
...@@ -5,11 +5,13 @@ FactoryBot.define do ...@@ -5,11 +5,13 @@ FactoryBot.define do
sequence(:name) { |n| "SOFTWARE-LICENSE-2.7/example_#{n}" } sequence(:name) { |n| "SOFTWARE-LICENSE-2.7/example_#{n}" }
trait :mit do trait :mit do
spdx_identifier { 'MIT' }
name { 'MIT' } name { 'MIT' }
end end
trait :apache_2_0 do trait :apache_2_0 do
name { 'Apache 2.0' } spdx_identifier { 'Apache-2.0' }
name { 'Apache 2.0 License' }
end end
end end
end end
...@@ -7,38 +7,91 @@ describe Gitlab::Ci::Reports::LicenseScanning::Report do ...@@ -7,38 +7,91 @@ describe Gitlab::Ci::Reports::LicenseScanning::Report do
describe '#violates?' do describe '#violates?' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:mit_license) { build(:software_license, :mit) }
let(:apache_license) { build(:software_license, :apache_2_0) }
context 'when a blacklisted license is found in the report' do context "when checking for violations using v1 license scan report" do
let(:mit_blacklist) { build(:software_license_policy, :blacklist, software_license: mit_license) } subject { build(:license_scan_report) }
let(:mit_license) { build(:software_license, :mit, spdx_identifier: nil) }
let(:apache_license) { build(:software_license, :apache_2_0, spdx_identifier: nil) }
before do before do
project.software_license_policies << mit_blacklist subject
.add_license(id: nil, name: 'MIT')
.add_dependency('rails')
end end
it { expect(subject.violates?(project.software_license_policies)).to be(true) } context 'when a blacklisted license is found in the report' do
end let(:mit_blacklist) { build(:software_license_policy, :blacklist, software_license: mit_license) }
context 'when a blacklisted license is discovered with a different casing for the name' do before do
let(:mit_blacklist) { build(:software_license_policy, :blacklist, software_license: mit_license) } project.software_license_policies << mit_blacklist
end
before do specify { expect(subject.violates?(project.software_license_policies)).to be(true) }
mit_license.update!(name: 'mit') end
project.software_license_policies << mit_blacklist
context 'when a blacklisted license is discovered with a different casing for the name' do
let(:mit_blacklist) { build(:software_license_policy, :blacklist, software_license: mit_license) }
before do
mit_license.update!(name: 'mit')
project.software_license_policies << mit_blacklist
end
specify { expect(subject.violates?(project.software_license_policies)).to be(true) }
end end
it { expect(subject.violates?(project.software_license_policies)).to be(true) } context 'when none of the licenses discovered in the report violate the blacklist policy' do
let(:apache_blacklist) { build(:software_license_policy, :blacklist, software_license: apache_license) }
before do
project.software_license_policies << apache_blacklist
end
specify { expect(subject.violates?(project.software_license_policies)).to be(false) }
end
end end
context 'when none of the licenses discovered in the report violate the blacklist policy' do context "when checking for violations using the v2 license scan reports" do
let(:apache_blacklist) { build(:software_license_policy, :blacklist, software_license: apache_license) } subject { build(:license_scan_report) }
before do context "when a blacklisted license with a SPDX identifier is also in the report" do
project.software_license_policies << apache_blacklist let(:mit_spdx_id) { 'MIT' }
let(:mit_license) { build(:software_license, :mit, spdx_identifier: mit_spdx_id) }
let(:mit_policy) { build(:software_license_policy, :blacklist, software_license: mit_license) }
before do
subject.add_license(id: mit_spdx_id, name: 'MIT License')
project.software_license_policies << mit_policy
end
specify { expect(subject.violates?(project.software_license_policies)).to be(true) }
end
context "when a blacklisted license does not have an SPDX identifier because it was provided by an end user" do
let(:custom_license) { build(:software_license, name: 'custom', spdx_identifier: nil) }
let(:custom_policy) { build(:software_license_policy, :blacklist, software_license: custom_license) }
before do
subject.add_license(id: nil, name: 'Custom')
project.software_license_policies << custom_policy
end
specify { expect(subject.violates?(project.software_license_policies)).to be(true) }
end end
it { expect(subject.violates?(project.software_license_policies)).to be(false) } context "when none of the licenses discovered match any of the blacklisted software policies" do
let(:apache_license) { build(:software_license, :apache_2_0, spdx_identifier: 'Apache-2.0') }
let(:apache_policy) { build(:software_license_policy, :blacklist, software_license: apache_license) }
before do
subject.add_license(id: nil, name: 'Custom')
subject.add_license(id: 'MIT', name: 'MIT License')
project.software_license_policies << apache_policy
end
specify { expect(subject.violates?(project.software_license_policies)).to be(false) }
end
end end
end end
......
...@@ -33,6 +33,17 @@ describe SoftwareLicensePolicy do ...@@ -33,6 +33,17 @@ describe SoftwareLicensePolicy do
end end
end end
describe ".by_spdx" do
let_it_be(:mit) { create(:software_license, :mit) }
let_it_be(:mit_policy) { create(:software_license_policy, software_license: mit) }
let_it_be(:apache) { create(:software_license, :apache_2_0) }
let_it_be(:apache_policy) { create(:software_license_policy, software_license: apache) }
it { expect(described_class.by_spdx(mit.spdx_identifier)).to match_array([mit_policy]) }
it { expect(described_class.by_spdx([mit.spdx_identifier, apache.spdx_identifier])).to match_array([mit_policy, apache_policy]) }
it { expect(described_class.by_spdx(SecureRandom.uuid)).to be_empty }
end
describe "#name" do describe "#name" do
specify { expect(subject.name).to eql(subject.software_license.name) } specify { expect(subject.name).to eql(subject.software_license.name) }
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment