quayio-scanner 0.1.5 → 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: 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: []