cocoapods-whitelist 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4723e3d52ded2d24e5ea0fd987f13c26e50e75f4b4f3d8e3c331bf3f0917e7d9
4
- data.tar.gz: 3cc1e0c08620d6d500299acfae29328e9a4230438073ea5d9b64defd3eea9b72
3
+ metadata.gz: a49d340692ecaa352c48b9970b6820303342d5063364296512169b5a317c5db5
4
+ data.tar.gz: 7e0d1d9a788778ec9dfd2a934a5ef87f7ae12f13d15d3455336fdbcc66966563
5
5
  SHA512:
6
- metadata.gz: f45764d3004aecd106e8003e4999dbb31636092376d093aecb0e68d0a6de19c7aa75372d43113b1f17147ceeb541af70f34647c7141c5efc319eae3f3418669d
7
- data.tar.gz: e8791f4a18accaef77551c5c864c923b2aecdd18072c9703716fff7c3668637d7f47b983b1c5db6aec96e165bda72adbc20e823f5a37fc7d5f9dc1508cd8dd25
6
+ metadata.gz: b48688ae3e2269e569c949229aea2a10b10a617d30ddff8ebb3c905c02984910097076c51de843783077d54539fe9fe32a9411ae61539c27edb78d516cc140db
7
+ data.tar.gz: 51d17dc94984f8ef2fdcec75e79bb50ef3c0c922af9edeaf7ee3d23360dc47d17d3cc9add6a174357b6db11752faa30b1ced9a712163721217efd4687ce32b08
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.2.0
2
+ ### Changed
3
+ - Avoid using whitelist to validate dependencies source
4
+
1
5
  ## 0.1.0
2
6
  - Dependency Confusion validation implementation
3
7
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cocoapods-whitelist (0.0.11)
4
+ cocoapods-whitelist (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,3 +1,3 @@
1
1
  module CocoapodsWhitelist
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,29 @@
1
+ require_relative '../model/sources'
2
+ require 'singleton'
3
+
4
+ # In charge of host the Pods names that comes from our private sources
5
+ #
6
+ # NOTE: The safest way to handle this was to host the complete specification and not only the pods
7
+ # names as rubydocs specified
8
+ # (https://www.rubydoc.info/github/CocoaPods/Core/Pod/Source#all_specs-instance_method)
9
+ # However, the execution time was considerably slower.
10
+ #
11
+ class SourceHelper
12
+ include Singleton
13
+ attr_accessor :specs
14
+
15
+ def initialize()
16
+ @specs ||= []
17
+ end
18
+
19
+ def setup(sources, private_sources)
20
+ private_sources = sources.select {|s| private_sources.include? s.url}
21
+ private_sources.each do |s|
22
+ @specs.concat s.pods
23
+ end
24
+ end
25
+
26
+ def is_filled
27
+ return !@specs.empty?
28
+ end
29
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative '../validator/source_validator'
2
+ require_relative '../helpers/source_helper'
2
3
  require_relative '../model/sources'
3
4
 
4
5
  module Pod
@@ -6,18 +7,28 @@ module Pod
6
7
  alias original_search_for search_for
7
8
  ## Filter specifications
8
9
  def search_for(dependency)
10
+ ## If you have a dependency problem, then no specification is returned from :search_for
9
11
  specifications = original_search_for(dependency)
10
12
 
11
- validator = SourceValidator.new(get_sources())
12
- filtered = validator.filter_dependency(dependency.root_name, specifications)
13
-
14
- if filtered.empty? && specifications.first ## If you have a dependency problem, then no specification is returned from :search_for
15
- Pod::UI.puts "Dependency #{dependency.root_name} comes from source #{specifications.first.spec_source.url} is NOT allowed".red
16
- Pod::UI.puts "If you thing this is a mistake, please check the whitelist".red
17
- raise Informative.new()
13
+ valid_specifications = validate_dependency(dependency,specifications)
14
+ if valid_specifications.size != specifications.size
15
+ Pod::UI.puts "WARNING: More than 1 specification for dependency #{dependency.root_name} was found.".yellow
16
+ Pod::UI.puts "WARNING: Check if this could be a potencial dependency inyection".red
18
17
  end
19
18
 
20
- specifications
19
+ valid_specifications
20
+ end
21
+
22
+ # Returns the valids specifications for a given dependency
23
+ # Params:
24
+ # +dependency+:: dependency to be validated
25
+ # +specifications+:: potencial unsecure specs
26
+ # @returs the result of the validation
27
+ def validate_dependency(dependency, specifications)
28
+ private_sources = get_private_sources()
29
+ SourceHelper.instance.setup(sources, private_sources) unless SourceHelper.instance.is_filled
30
+ validator = SourceValidator.new(SourceHelper.instance.specs, private_sources)
31
+ return validator.filter_dependency(dependency.root_name, specifications)
21
32
  end
22
33
  end
23
34
  end
@@ -1,6 +1,3 @@
1
- def get_sources
2
- {
3
- "public" => "https://cdn.cocoapods.org/",
4
- "private" => "git@github.com:mercadolibre/mobile-ios_specs.git"
5
- }
1
+ def get_private_sources
2
+ [ "git@github.com:mercadolibre/mobile-ios_specs.git" ]
6
3
  end
@@ -1,52 +1,33 @@
1
- require_relative '../client/whitelist_resolver'
2
1
  require 'singleton'
3
2
 
4
3
  class SourceValidator
5
- attr_accessor :sources
6
- def initialize(sources)
7
- @sources = sources
4
+ attr_accessor :private_specs
5
+ attr_accessor :private_sources
6
+ def initialize(private_specs, private_sources)
7
+ @private_specs = private_specs
8
+ @private_sources = private_sources
8
9
  end
9
10
 
11
+ # Filters the valids specifications for a given pod
12
+ # Params:
13
+ # +pod+:: podname to be validated
14
+ # +specifications+:: potencial unsecure specs
15
+ # @returs valid specs
10
16
  def filter_dependency(pod, specifications)
11
- ## Avoid checking the same pod many times
12
- return [specifications.first] if DependencyCounter.instance.is_checked(pod) && !specifications.empty?
13
-
14
- filtered = specifications.select { |spec| spec_is_valid(pod, spec) }
15
-
16
- return filtered
17
+ return specifications.select { |spec| spec_is_valid(pod, spec) }
17
18
  end
18
19
 
19
20
  def spec_is_valid(pod, spec)
20
-
21
21
  # Allow external dependencies (using :git or :path), which create a local podspec
22
22
  return true if !spec.defined_in_file.nil? && spec.defined_in_file.to_s.include?('/Pods/Local Podspecs')
23
23
 
24
- # Allow every dependency that comes from our private specs sources
25
- return true if spec.spec_source.url == @sources["private"]
26
-
27
- whitelist = WhitelistResolver.instance.get_whitelist
28
- whitelist.each { |dependency|
29
- next unless dependency.name == pod
30
- return true unless spec.spec_source.url != @sources[dependency.source]
31
- }
32
- return false
33
- end
24
+ # Allow every dependency that comes from our privates sources
25
+ return true if @private_sources.include? spec.spec_source.url
34
26
 
35
- end
27
+ # NO dependency that comes from a public source should be in our private specs
28
+ return true if !@private_specs.include? spec.name
36
29
 
37
- class DependencyCounter
38
- include Singleton
39
- attr_accessor :dependencies_checked
40
-
41
- def initialize()
42
- @dependencies_checked ||= []
43
- end
44
-
45
- def is_checked(podname)
46
- included = @dependencies_checked.include? podname
47
- @dependencies_checked.push(podname) unless included
48
-
49
- return included
30
+ return false
50
31
  end
51
32
 
52
33
  end
@@ -0,0 +1,66 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe SourceHelper do
4
+ describe 'behaviour' do
5
+ it 'should group the private specs from the differents private sources' do
6
+
7
+ SourceHelper.instance.specs = [] # Avoid a non-empty SourceHelper
8
+
9
+ private_sources = [ "git@github.com:mercadolibre/mobile-ios_specs.git", "git@github.com:testable/testable_specs.git" ]
10
+
11
+ private_meli_specs = ["MyMELIPod1", "MyMELIPod2", "MyMELIPod3"]
12
+ meli_mock = mock()
13
+ meli_mock.stubs(:url).returns("git@github.com:mercadolibre/mobile-ios_specs.git")
14
+ meli_mock.stubs(:pods).returns(private_meli_specs)
15
+
16
+ private_cocoapods_cdn_specs = ["MyPublicPod1", "MyPublicPod2", "MyPublicPod2"]
17
+ cocoapods_cdn_mock = mock()
18
+ cocoapods_cdn_mock.stubs(:url).returns("https://cdn.cocoapods.org/")
19
+ cocoapods_cdn_mock.stubs(:pods).returns(private_cocoapods_cdn_specs)
20
+
21
+ private_testable_specs = ["MyTestablePod1", "MyTestablePod2", "MyTestablePod2"]
22
+ testable_mock = mock()
23
+ testable_mock.stubs(:url).returns("git@github.com:testable/testable_specs.git")
24
+ testable_mock.stubs(:pods).returns(private_testable_specs)
25
+
26
+ sources = [meli_mock, cocoapods_cdn_mock, testable_mock]
27
+
28
+ expected_result = [ "MyMELIPod1", "MyMELIPod2", "MyMELIPod3", "MyTestablePod1", "MyTestablePod2", "MyTestablePod2" ]
29
+
30
+ validator = SourceHelper.instance.setup(sources, private_sources)
31
+
32
+ SourceHelper.instance.specs.size.should.equal 6
33
+ SourceHelper.instance.is_filled.should.be.true
34
+ SourceHelper.instance.specs.should.equal expected_result
35
+ end
36
+
37
+ it 'should not be filled if not specs been added' do
38
+
39
+ SourceHelper.instance.specs = [] # Avoid a non-empty SourceHelper
40
+
41
+ private_sources = [ "git@github.com:mercadolibre/mobile-ios_specs.git", "git@github.com:testable/testable_specs.git" ]
42
+
43
+ private_meli_specs = []
44
+ meli_mock = mock()
45
+ meli_mock.stubs(:url).returns("git@github.com:mercadolibre/mobile-ios_specs.git")
46
+ meli_mock.stubs(:pods).returns(private_meli_specs)
47
+
48
+ private_cocoapods_cdn_specs = []
49
+ cocoapods_cdn_mock = mock()
50
+ cocoapods_cdn_mock.stubs(:url).returns("https://cdn.cocoapods.org/")
51
+ cocoapods_cdn_mock.stubs(:pods).returns(private_cocoapods_cdn_specs)
52
+
53
+ private_testable_specs = []
54
+ testable_mock = mock()
55
+ testable_mock.stubs(:url).returns("git@github.com:testable/testable_specs.git")
56
+ testable_mock.stubs(:pods).returns(private_testable_specs)
57
+
58
+ sources = [meli_mock, cocoapods_cdn_mock, testable_mock]
59
+
60
+ validator = SourceHelper.instance.setup(sources, private_sources)
61
+
62
+ SourceHelper.instance.specs.size.should.equal 0
63
+ SourceHelper.instance.is_filled.should.not.be.true
64
+ end
65
+ end
66
+ end
@@ -2,91 +2,68 @@ require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
3
  describe SourceValidator do
4
4
  describe 'functionality' do
5
- it 'external dependency that is not on the whitelist should not be valid' do
5
+ it 'external dependency that comes from a public source should be valid' do
6
6
 
7
- sources = {
8
- "public" => "https://cdn.cocoapods.org/",
9
- "private" => "git@github.com:mercadolibre/mobile-ios_specs.git"
10
- }
7
+ private_sources = [ "git@github.com:mercadolibre/mobile-ios_specs.git" ]
8
+ private_specs = ["MyPod1", "MyPod1", "MyPod3"]
11
9
 
12
10
  stub_url = stub(:url => 'https://cdn.cocoapods.org/')
13
11
  spec_mock = mock()
14
12
  spec_mock.stubs(:spec_source).returns(stub_url)
15
13
  spec_mock.stubs(:defined_in_file).returns(nil?)
14
+ spec_mock.stubs(:name).returns("MyExternalPod")
16
15
 
17
- validator = SourceValidator.new(sources)
18
- filtered = validator.filter_dependency('MyExternalPod', [spec_mock])
19
-
20
- filtered.should.empty?
16
+ validator = SourceValidator.new(private_specs, private_sources)
17
+ filtered = validator.filter_dependency("MyExternalPod", [spec_mock])
21
18
 
19
+ filtered.size.should.equal 1
22
20
  end
23
21
 
24
- it 'external dependency that is on the whitelist should be valid' do
25
-
26
- sources = {
27
- "public" => "https://cdn.cocoapods.org/",
28
- "private" => "git@github.com:mercadolibre/mobile-ios_specs.git"
29
- }
22
+ it 'internal dependency that comes from a public source should not be valid' do
23
+ private_sources = [ "git@github.com:mercadolibre/mobile-ios_specs.git" ]
24
+ private_specs = ["MyPod1", "MyPod1", "MyPod3", "MyInternalPod"]
30
25
 
31
26
  stub_url = stub(:url => 'https://cdn.cocoapods.org/')
32
27
  spec_mock = mock()
33
28
  spec_mock.stubs(:spec_source).returns(stub_url)
34
29
  spec_mock.stubs(:defined_in_file).returns(nil?)
30
+ spec_mock.stubs(:name).returns("MyInternalPod")
35
31
 
36
- validator = SourceValidator.new(sources)
37
- filtered = validator.filter_dependency('RxSwift', [spec_mock])
38
-
39
- filtered.size.should.equal 1
32
+ validator = SourceValidator.new(private_specs, private_sources)
33
+ filtered = validator.filter_dependency("MyInternalPod", [spec_mock])
40
34
 
35
+ filtered.should.empty?
41
36
  end
42
37
 
43
38
  it 'internal dependency that comes from private source should be valid' do
44
- sources = {
45
- "public" => "https://cdn.cocoapods.org/",
46
- "private" => "git@github.com:mercadolibre/mobile-ios_specs.git"
47
- }
39
+
40
+ private_sources = [ "git@github.com:mercadolibre/mobile-ios_specs.git" ]
41
+ private_specs = ["MyPod1", "MyPod1", "MyPod3", "MyInternalPod"]
48
42
 
49
43
  stub_url = stub(:url => 'git@github.com:mercadolibre/mobile-ios_specs.git')
50
44
  spec_mock = mock()
51
45
  spec_mock.stubs(:spec_source).returns(stub_url)
52
46
  spec_mock.stubs(:defined_in_file).returns(nil?)
47
+ spec_mock.stubs(:name).returns("MyInternalPod")
53
48
 
54
- validator = SourceValidator.new(sources)
55
- filtered = validator.filter_dependency('MLMyPod', [spec_mock])
49
+ validator = SourceValidator.new(private_specs, private_sources)
50
+ filtered = validator.filter_dependency("MyInternalPod", [spec_mock])
56
51
 
57
52
  filtered.size.should.equal 1
58
-
59
- end
60
-
61
- it 'internal dependency that comes from unknown source should not be valid' do
62
- sources = {
63
- "public" => "https://cdn.cocoapods.org/",
64
- "private" => "git@github.com:mercadolibre/mobile-ios_specs.git"
65
- }
66
-
67
- stub_url = stub(:url => 'https://cdn.malicious.source.org/')
68
- spec_mock = mock()
69
- spec_mock.stubs(:spec_source).returns(stub_url)
70
- spec_mock.stubs(:defined_in_file).returns(nil?)
71
-
72
- validator = SourceValidator.new(sources)
73
- filtered = validator.filter_dependency('MLOnDemandResources', [spec_mock])
74
-
75
- filtered.should.empty?
76
53
  end
77
54
 
78
55
  it 'development pods should be valid' do
79
- sources = {
80
- "public" => "https://cdn.cocoapods.org/",
81
- "private" => "git@github.com:mercadolibre/mobile-ios_specs.git"
82
- }
56
+
57
+ private_sources = [ "git@github.com:mercadolibre/mobile-ios_specs.git" ]
58
+ private_specs = ["MyPod1", "MyPod1", "MyPod3", "MyInternalPod"]
83
59
 
84
60
  stub_url = stub(:url => '')
85
61
  spec_mock = mock()
86
62
  spec_mock.stubs(:spec_source).returns(stub_url)
87
63
  spec_mock.stubs(:defined_in_file).returns('./Users/Pods/Local Podspecs/MLMyDevelopmentPod.podspec')
64
+ spec_mock.stubs(:name).returns("MLMyDevelopmentPod")
88
65
 
89
- validator = SourceValidator.new(sources)
66
+ validator = SourceValidator.new(private_specs, private_sources)
90
67
  filtered = validator.filter_dependency('MLMyDevelopmentPod', [spec_mock])
91
68
 
92
69
  filtered.size.should.equal 1
@@ -1,9 +1,11 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
+ WHITELIST_PATH = './spec/mocks/whitelist.json'
4
+
3
5
  describe WhitelistResolver do
4
6
  describe 'functionality' do
5
7
  it 'whitelist should be loaded from an specific url' do
6
- whitelist = WhitelistResolver.instance.get_whitelist(WHITELIST_FILE)
8
+ whitelist = WhitelistResolver.instance.get_whitelist(WHITELIST_PATH)
7
9
  whitelist.size.should.equal 6
8
10
  end
9
11
 
@@ -13,7 +15,7 @@ describe WhitelistResolver do
13
15
  end
14
16
 
15
17
  it 'whitelist should not be loaded twice' do
16
- WhitelistResolver.instance.get_whitelist(WHITELIST_FILE)
18
+ WhitelistResolver.instance.get_whitelist(WHITELIST_PATH)
17
19
  loaded = WhitelistResolver.instance.whitelist_loaded
18
20
 
19
21
  loaded.should.be.true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-whitelist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mobile Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-04 00:00:00.000000000 Z
11
+ date: 2021-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -59,6 +59,7 @@ files:
59
59
  - lib/cocoapods-whitelist/command.rb
60
60
  - lib/cocoapods-whitelist/command/whitelist.rb
61
61
  - lib/cocoapods-whitelist/gem_version.rb
62
+ - lib/cocoapods-whitelist/helpers/source_helper.rb
62
63
  - lib/cocoapods-whitelist/hook.rb
63
64
  - lib/cocoapods-whitelist/hook/resolver.rb
64
65
  - lib/cocoapods-whitelist/model/allowed_dependency.rb
@@ -87,6 +88,7 @@ files:
87
88
  - spec/mocks/with_whitelisted_dependency_fixed_versions_variable.podspec
88
89
  - spec/mocks/without_dependencies.podspec
89
90
  - spec/mocks/without_version.podspec
91
+ - spec/source_helper_spec.rb
90
92
  - spec/source_validator_spec.rb
91
93
  - spec/spec_helper.rb
92
94
  - spec/whitelist_resolver_spec.rb
@@ -137,6 +139,7 @@ test_files:
137
139
  - spec/mocks/with_whitelisted_dependency_fixed_versions_variable.podspec
138
140
  - spec/mocks/without_dependencies.podspec
139
141
  - spec/mocks/without_version.podspec
142
+ - spec/source_helper_spec.rb
140
143
  - spec/source_validator_spec.rb
141
144
  - spec/spec_helper.rb
142
145
  - spec/whitelist_resolver_spec.rb