class Examine::CLI::Clair

Entrypoint into the `examine clair` subcommand.

Constants

DOWNLOAD_PATH
EXECUTABLES

Public Instance Methods

scan(image) click to toggle source
# File lib/examine/cli/clair.rb, line 36
def scan(image)
  start

  system "docker pull #{image}"
  system scan_command_for(image, options)
end
start() click to toggle source
# File lib/examine/cli/clair.rb, line 19
def start
  ensure_docker_installed!
  return if started?

  spawn clair_db
  wait_until clair_db_running?

  spawn clair_local_scan
  wait_until clair_local_scan_running?
  wait_until clair_local_scan_api_reachable?
end
status() click to toggle source
# File lib/examine/cli/clair.rb, line 44
def status
  system 'docker ps -a | grep clair'
end
stop() click to toggle source
# File lib/examine/cli/clair.rb, line 49
def stop
  system "docker stop $(docker ps | grep -v CONT | grep clair- | awk '{ print $1 }')"
  system 'docker system prune -f'
end

Private Instance Methods

clair_db() click to toggle source
# File lib/examine/cli/clair.rb, line 117
def clair_db
  'docker run -d --name clair-db --network=host arminc/clair-db:latest'
end
clair_db_running?() click to toggle source
# File lib/examine/cli/clair.rb, line 113
def clair_db_running?
  'docker ps --filter="name=clair-db" --filter="status=running" --filter="expose=5432/tcp" | grep -v CONT'
end
clair_download_url() click to toggle source
# File lib/examine/cli/clair.rb, line 91
def clair_download_url
  exe = EXECUTABLES["#{Gem::Platform.local.cpu}-#{Gem::Platform.local.os}"]
  return File.join(DOWNLOAD_PATH, options[:scanner_version], exe) if exe

  raise 'clair-scanner could not be found in your PATH. Download from https://github.com/arminc/clair-scanner/releases'
end
clair_exe() click to toggle source
# File lib/examine/cli/clair.rb, line 60
def clair_exe
  @clair_exe ||= executable_exists?('clair-scanner') || download_clair
end
clair_ip() click to toggle source
# File lib/examine/cli/clair.rb, line 76
def clair_ip
  options[:ip] || Socket.ip_address_list[1].ip_address
end
clair_local_scan() click to toggle source
# File lib/examine/cli/clair.rb, line 121
def clair_local_scan
  'docker run --restart=unless-stopped -p 6060:6060 --add-host=postgres:0.0.0.0 --network=host -d --name clair arminc/clair-local-scan:latest'
end
clair_local_scan_api_reachable?(url = options[:url]) click to toggle source
# File lib/examine/cli/clair.rb, line 129
def clair_local_scan_api_reachable?(url = options[:url])
  "curl -s #{url}/v1/namespaces > /dev/null"
end
clair_local_scan_running?() click to toggle source
# File lib/examine/cli/clair.rb, line 125
def clair_local_scan_running?
  'docker ps --filter="name=clair" --filter="status=running" --filter="expose=6060/tcp" | grep -v CONT'
end
download_clair() click to toggle source
# File lib/examine/cli/clair.rb, line 84
def download_clair
  File.join(Dir.tmpdir, 'clair-scanner').tap do |exe|
    Down.download(clair_download_url, destination: exe)
    `chmod +x #{exe}`
  end
end
ensure_docker_installed!() click to toggle source
# File lib/examine/cli/clair.rb, line 109
def ensure_docker_installed!
  raise 'docker was not detected on the system' unless executable_exists?('docker')
end
executable_exists?(exe) click to toggle source
# File lib/examine/cli/clair.rb, line 80
def executable_exists?(exe)
  ENV['PATH'].split(':').map { |x| File.join(x, exe) }.find { |x| File.exist?(x) }
end
scan_command_for(image, options) click to toggle source
# File lib/examine/cli/clair.rb, line 64
def scan_command_for(image, options)
  command = [
    clair_exe, "-c #{options[:url]}",
    "--ip #{clair_ip}",
    '--threshold High',
    '--reportAll=false',
    "-r #{options[:report]}", "-l #{options[:log]}", image
  ]
  command.insert(-2, "-w #{options[:whitelist]}") if options[:whitelist]
  command.join(' ')
end
started?() click to toggle source
# File lib/examine/cli/clair.rb, line 56
def started?
  status
end
wait() click to toggle source
# File lib/examine/cli/clair.rb, line 98
def wait
  print '.'
  sleep 1
end
wait_until(command) click to toggle source
# File lib/examine/cli/clair.rb, line 103
def wait_until(command)
  Timeout.timeout(60, nil, command) do
    wait until system(command)
  end
end