cocoapods-whitelist 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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