quayio-scanner 0.1.5 → 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: 5df176d74b68e0b31a5408b2be36bac9c0cb2171650acb160cfedd90a143de2c
4
- data.tar.gz: aab6b7098d7a848294613428d8b514589c949f5d9f1fdf9041af06932d12856c
3
+ metadata.gz: 62a2ef4b20397cec2c5a06cd141f61c4f9b0ab00ccdef0dbc235f39ada492232
4
+ data.tar.gz: a6bf579dc9491d3c4a8cc5d002148bed5bdadba1bb7b28ec17a3b4f6c429ac75
5
5
  SHA512:
6
- metadata.gz: 1da63def2a66714fff1b69b709150b444a0b149f7da03c1a9bcdec87f895a1b73a44887d9ded63c928dca958f5edc82ecc06a074957c3103f96958dccb0f2183
7
- data.tar.gz: a0c809340d55c456aa639ecebe00926722ece6f156efee325f713fcb25ef371ca8cc44ad828665767175f31fce558300665eb976ebbb8d9d8ac346d386cd1b96
6
+ metadata.gz: fbf6cc4db97ce33820084256632012ecb42d50ea049d0f5f1a09cee19119edc92d97cf4a2b32ac5f12be0bd3594d71fd4bb7ed5050382fbf9c83287652afb529
7
+ data.tar.gz: c71f7a7dc9aaf747ea57485988a7fe261bddc4c69425fb7a33f07c550ee503c4bfd0e051496853333e9cba1ff5da6a2cc4f3cd4fa2d8819d3703d60937470a43
@@ -0,0 +1,11 @@
1
+ Style/FrozenStringLiteralComment:
2
+ Enabled: false
3
+
4
+ Style/Documentation:
5
+ Enabled: false
6
+
7
+ Metrics/MethodLength:
8
+ Max: 50
9
+
10
+ Metrics/BlockLength:
11
+ Max: 200
@@ -44,8 +44,9 @@ class CheckContainerVulnerabilities < Sensu::Plugin::Check::CLI
44
44
  proc: proc { |w| w.split(',') }
45
45
 
46
46
  def run
47
- status, message = Quayio::Scanner::Check.new(
48
- config[:docker_url], config[:quayio_token], config[:whitelist]).run
47
+ status, message = Quayio::Scanner::Check.new(config[:docker_url],
48
+ config[:quayio_token],
49
+ config[:whitelist]).run
49
50
 
50
51
  if status == :ok
51
52
  ok message
@@ -1,5 +1,7 @@
1
- require 'quayio/scanner/version'
2
1
  require 'quayio/scanner/check'
2
+ require 'quayio/scanner/image'
3
+ require 'quayio/scanner/repository'
4
+ require 'quayio/scanner/version'
3
5
 
4
6
  module Quayio
5
7
  module Scanner
@@ -1,19 +1,10 @@
1
- require 'quayio/scanner/image'
2
1
  require 'docker'
3
2
 
4
3
  module Quayio
5
4
  module Scanner
6
- class Check < Struct.new(:docker_url, :quayio_token, :whitelist)
5
+ Check = Struct.new(:docker_url, :quayio_token, :whitelist) do
7
6
  def run
8
7
  Docker.url = docker_url
9
- containers = Docker::Container.all
10
- .map { |dc| dc.json['Config']['Image'] }
11
- .uniq
12
-
13
- vulnerable_images = containers
14
- .map { |container| Image.new(container, quayio_token, whitelist) }
15
- .select(&:vulnerable?)
16
- .map(&:name)
17
8
 
18
9
  if vulnerable_images.empty?
19
10
  [:ok, "#{containers.size} Containers are ok"]
@@ -21,6 +12,22 @@ module Quayio
21
12
  [:critical, "The images are insecure: #{vulnerable_images.join(', ')}"]
22
13
  end
23
14
  end
15
+
16
+ private
17
+
18
+ def containers
19
+ Docker::Container
20
+ .all
21
+ .map { |dc| dc.json['Config']['Image'] }
22
+ .uniq
23
+ end
24
+
25
+ def vulnerable_images
26
+ containers
27
+ .map { |container| Image.new(container, quayio_token, whitelist) }
28
+ .select(&:vulnerable?)
29
+ .map(&:name)
30
+ end
24
31
  end
25
32
  end
26
33
  end
@@ -1,78 +1,46 @@
1
- require 'json'
2
- require 'rest-client'
3
-
4
1
  module Quayio
5
2
  module Scanner
6
- class Image < Struct.new(:name, :quayio_token, :whitelist)
7
- RELEVANT_SEVERITIES = %w(High Critical)
8
- MAX_ATTEMPTS = 5
3
+ class Image
4
+ RELEVANT_SEVERITIES = %w[High Critical].freeze
5
+ QUAY_IO_REPO_NAME = %r{quay.io\/(?<org>[\w-]+)\/(?<repo>[\w-]+):(?<tag>[\w\.-]+)}.freeze
6
+
7
+ attr_reader :name, :whitelist, :repository
8
+
9
+ def initialize(name, quayio_token, whitelist)
10
+ @name = name
11
+ @whitelist = whitelist
12
+
13
+ @name.match(QUAY_IO_REPO_NAME) do |r|
14
+ org, repo, tag = r.captures
15
+ @repository = Repository.new(quayio_token, org, repo, tag)
16
+ end
17
+ end
9
18
 
10
19
  def vulnerable?
11
- quayio? && image_exists? && scanned? && high_vulnerabilities_present?
20
+ quayio? && scanned? && vulnerabilities_present?
12
21
  end
13
22
 
14
23
  private
15
24
 
16
25
  def quayio?
17
- name.match(%r{^quay.io\/})
18
- end
19
-
20
- def image_exists?
21
- raw_image
26
+ # safe guard, do not trust QUAY_IO_REPO_NAME regex match
27
+ !!name.match(%r{^quay.io\/})
22
28
  end
23
29
 
24
30
  def scanned?
25
31
  raw_scan['status'] == 'scanned'
26
32
  end
27
33
 
28
- def high_vulnerabilities_present?
29
- raw_scan['data']['Layer']['Features'].detect do |f|
30
- f['Vulnerabilities'] && f['Vulnerabilities'].detect do |v|
31
- RELEVANT_SEVERITIES.include?(v['Severity']) &&
32
- !whitelist.include?(v['Name'])
34
+ def vulnerabilities_present?
35
+ !!raw_scan['data']['Layer']['Features'].detect do |f|
36
+ f['Vulnerabilities']&.detect do |v|
37
+ RELEVANT_SEVERITIES.include?(v['Severity']) && !whitelist.include?(v['Name'])
33
38
  end
34
39
  end
35
40
  end
36
41
 
37
- def repo
38
- name.split(':').first.gsub(%r{quay.io\/}, '')
39
- end
40
-
41
- def tag
42
- name.split(':').last
43
- end
44
-
45
- def raw_image
46
- return @raw_image if defined? @raw_image
47
-
48
- (1..MAX_ATTEMPTS).each do |attempt|
49
- begin
50
- response = RestClient.get(
51
- "https://quay.io/api/v1/repository/#{repo}/tag/#{tag}/images",
52
- authorization: "Bearer #{quayio_token}",
53
- accept: :json)
54
- rescue RestClient::ExceptionWithResponse => err
55
- return nil if err.http_code == 404 # ignore unknown repos
56
- if err.http_code == 520 and attempt < MAX_ATTEMPTS
57
- sleep(rand(10))
58
- next
59
- end
60
- raise err
61
- end
62
- @raw_image = JSON.parse(response)['images'].first
63
- return @raw_image
64
- end
65
- end
66
-
67
42
  def raw_scan
68
- return @raw_scan if defined? @raw_scan
69
-
70
- @raw_scan = begin
71
- JSON.parse(
72
- RestClient.get("https://quay.io/api/v1/repository/#{repo}/image/#{raw_image['id']}/security?vulnerabilities=true",
73
- authorization: "Bearer #{quayio_token}", accept: :json)
74
- )
75
- end
43
+ @raw_scan ||= repository.scan
76
44
  end
77
45
  end
78
46
  end
@@ -0,0 +1,42 @@
1
+ require 'rest-client'
2
+ require 'json'
3
+
4
+ module Quayio
5
+ module Scanner
6
+ Repository = Struct.new(:quayio_token, :org, :repo, :tag) do
7
+ MAX_ATTEMPTS = 5
8
+
9
+ def id
10
+ @id ||= fetch_id
11
+ end
12
+
13
+ def scan
14
+ api_call("/image/#{id}/security?vulnerabilities=true")
15
+ end
16
+
17
+ private
18
+
19
+ def fetch_id
20
+ result = api_call("/tag/#{tag}/images")
21
+ (result['images'].first)['id']
22
+ end
23
+
24
+ def api_call(uri)
25
+ (1..Float::INFINITY).each do |attempt|
26
+ begin
27
+ response = RestClient.get(
28
+ "https://quay.io/api/v1/repository/#{org}/#{repo}#{uri}",
29
+ authorization: "Bearer #{quayio_token}",
30
+ accept: :json
31
+ )
32
+ return JSON.parse(response)
33
+ rescue RestClient::ExceptionWithResponse => e
34
+ raise e if e.http_code != 520 || attempt >= MAX_ATTEMPTS
35
+
36
+ sleep(rand(10))
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  module Quayio
2
2
  module Scanner
3
- VERSION = '0.1.5'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
@@ -12,6 +12,8 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = 'https://github.com/aboutsource/quayio-scanner'
13
13
  spec.license = 'MIT'
14
14
 
15
+ spec.required_ruby_version = '>= 2.4.0'
16
+
15
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
18
  f.match(%r{^(test|spec|features)/})
17
19
  end
@@ -21,7 +23,7 @@ Gem::Specification.new do |spec|
21
23
  spec.add_dependency 'docker-api', '~> 1.33'
22
24
  spec.add_dependency 'rest-client', '~> 2.0'
23
25
  spec.add_dependency 'sensu-plugin', '~> 2.1'
24
- spec.add_development_dependency 'bundler', '~> 1.14'
26
+ spec.add_development_dependency 'bundler'
25
27
  spec.add_development_dependency 'rake', '~> 10.0'
26
28
  spec.add_development_dependency 'rspec', '~> 3.7'
27
29
  spec.add_development_dependency 'rubocop', '~> 0.49'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quayio-scanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Meichsner
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-31 00:00:00.000000000 Z
11
+ date: 2020-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.14'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.14'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +108,7 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.49'
111
- description:
111
+ description:
112
112
  email:
113
113
  - benjamin.meichsner@aboutsource.net
114
114
  executables:
@@ -117,6 +117,7 @@ extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
119
  - ".gitignore"
120
+ - ".rubocop.yml"
120
121
  - Gemfile
121
122
  - LICENSE.txt
122
123
  - README.md
@@ -125,13 +126,14 @@ files:
125
126
  - lib/quayio/scanner.rb
126
127
  - lib/quayio/scanner/check.rb
127
128
  - lib/quayio/scanner/image.rb
129
+ - lib/quayio/scanner/repository.rb
128
130
  - lib/quayio/scanner/version.rb
129
131
  - quayio-scanner.gemspec
130
132
  homepage: https://github.com/aboutsource/quayio-scanner
131
133
  licenses:
132
134
  - MIT
133
135
  metadata: {}
134
- post_install_message:
136
+ post_install_message:
135
137
  rdoc_options: []
136
138
  require_paths:
137
139
  - lib
@@ -139,15 +141,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
141
  requirements:
140
142
  - - ">="
141
143
  - !ruby/object:Gem::Version
142
- version: '0'
144
+ version: 2.4.0
143
145
  required_rubygems_version: !ruby/object:Gem::Requirement
144
146
  requirements:
145
147
  - - ">="
146
148
  - !ruby/object:Gem::Version
147
149
  version: '0'
148
150
  requirements: []
149
- rubygems_version: 3.1.2
150
- signing_key:
151
+ rubygems_version: 3.1.4
152
+ signing_key:
151
153
  specification_version: 4
152
154
  summary: Scan quay.io for vulnerabilties in running docker containers.
153
155
  test_files: []