Remove worker logic from API repo

This commit is contained in:
Jonathan Claudius 2018-06-25 17:28:07 -04:00
Родитель 18c5675bf9
Коммит d357027aa3
9 изменённых файлов: 92 добавлений и 238 удалений

Просмотреть файл

@ -1,14 +0,0 @@
#!/usr/bin/env ruby
$:.unshift File.join(File.dirname(__FILE__), "../lib")
require 'ssh_scan'
require 'ssh_scan_api/worker'
# Usage: ruby ./bin/ssh_scan_worker [test/development/production]
env = ARGV[0] || "development"
worker = SSHScan::Worker.new()
worker.set_environment(env.chomp)
worker.run!

Просмотреть файл

@ -1,14 +1,6 @@
test:
adapter: postgresql
database: ssh_observatory
username: sshobs
host: 127.0.0.1
pool: 5
timeout: 5000
development:
adapter: postgresql
database: ssh_observatory
username: sshobs
host: database
pool: 20
timeout: 5000
adapter: postgresql
database: ssh_observatory
username: sshobs
host: 127.0.0.1
pool: 5
timeout: 5000

Просмотреть файл

@ -1,9 +1,5 @@
version: '2'
services:
base:
build:
context: .
dockerfile: ./docker/base
database:
build:
context: .
@ -29,7 +25,6 @@ services:
- default
restart: always
depends_on:
- "base"
- "database"
stdin_open: true
tty: true
@ -44,7 +39,6 @@ services:
networks:
- default
depends_on:
- "base"
- "database"
- "api"
restart: always

Просмотреть файл

@ -1,5 +1,13 @@
FROM sshscanapi_base:latest
MAINTAINER Jonathan Claudius
COPY ./Gemfile /app/Gemfile
COPY ./ssh_scan_api.gemspec /app/ssh_scan_api.gemspec
COPY ./db /app/db
COPY ./docker/wait-for-it.sh /app/docker/wait-for-it.sh
RUN cd /app && \
gem install bundler && \
bundle install && \
chmod u+x /app/docker/wait-for-it.sh
COPY ./lib /app/lib
COPY ./bin /app/bin
COPY ./config/database.yml /app/config/database.yml

Просмотреть файл

@ -1,13 +0,0 @@
FROM ruby:latest AS base
MAINTAINER Jonathan Claudius
COPY ./Gemfile /app/Gemfile
COPY ./ssh_scan_api.gemspec /app/ssh_scan_api.gemspec
COPY ./lib /app/lib
COPY ./bin /app/bin
COPY ./db /app/db
COPY ./docker/wait-for-it.sh /app/docker/wait-for-it.sh
RUN cd /app && \
gem install bundler && \
bundle install && \
chmod u+x /app/docker/wait-for-it.sh

Просмотреть файл

@ -1,8 +0,0 @@
FROM sshscanapi_base:latest
MAINTAINER Jonathan Claudius
COPY ./lib /app/lib
COPY ./bin /app/bin
COPY ./data /app/data
COPY ./config/policies/ /app/config/policies
COPY ./config/database.yml /app/config/database.yml
COPY ./Rakefile /app/Rakefile

Просмотреть файл

@ -119,26 +119,88 @@ https://github.com/mozilla/ssh_scan_api/wiki/ssh_scan-Web-API\n"
begin
scan = Scan.find_by("scan_id": uuid)
if scan.nil?
return {"scan" => "UNKNOWN"}.to_json
end
case scan.state
when "QUEUED"
return {"status" => "QUEUED"}.to_json
when "ERRORED"
return {"status" => "ERRORED"}.to_json
when "RUNNNING"
return {"status" => "RUNNNING"}.to_json
when "COMPLETED"
return scan.raw_scan
else
return {"status" => "UNKNOWN"}.to_json
end
ensure
ActiveRecord::Base.connection_pool.release_connection
end
end
get '/work' do
# Always require authentication for this route
#authenticated?
worker_id = params[:worker_id]
#uuid = settings.db.next_scan_in_queue
scan = SSHScan::Scan.find_by("state": "QUEUED")
if scan
scan.state = "RUNNING"
scan.worker_id = worker_id
scan.save
return {
"work" => {
"uuid" => scan.scan_id,
"target" => scan.target,
"port" => scan.port,
}
}.to_json
else
return {"work" => false}.to_json
end
end
post '/work/results/:worker_id/:uuid' do
# Always require authentication for this route
#authenticated?
worker_id = params[:worker_id]
uuid = params[:uuid]
result = JSON.parse(request.body.first).first
if worker_id.empty? || uuid.empty?
return {"accepted" => "false"}.to_json
end
begin
scan = Scan.find_by("scan_id": uuid)
# Make sure we have a relevant match scan
return {"accepted" => "false"}.to_json unless scan
if result["error"]
scan.state = "ERRORED"
scan.worker_id = worker_id
scan.raw_scan = result.to_json
scan.save
else
scan.state = "COMPLETED"
scan.worker_id = worker_id
scan.raw_scan = result.to_json
scan.save
end
ensure
ActiveRecord::Base.connection_pool.release_connection
end
if scan.nil?
return {"scan" => "UNKNOWN"}.to_json
end
case scan.state
when "QUEUED"
return {"status" => "QUEUED"}.to_json
when "ERRORED"
return {"status" => "ERRORED"}.to_json
when "RUNNNING"
return {"status" => "RUNNNING"}.to_json
when "COMPLETED"
return scan.raw_scan
else
return {"scan" => "UNKNOWN"}.to_json
end
return {"accepted" => "true"}
end
get '/stats' do

Просмотреть файл

@ -1,78 +0,0 @@
require 'ssh_scan/scan_engine'
require 'ssh_scan_api/version'
require 'ssh_scan_api/models/scan'
require 'logger'
require 'yaml'
class SSHScan::Worker
def initialize()
@worker_id = SecureRandom.uuid
@log = Logger.new(STDOUT)
@fingerprint_database_path = File.join(File.dirname(__FILE__),"../../data/fingerprints.yml")
@policy_path = File.join(File.dirname(__FILE__),"../../config/policies/mozilla_modern.yml")
@poll_interval = 1
end
def set_environment(environment)
ActiveRecord::Base.logger = Logger.new(STDOUT)
config = YAML.load_file(File.join(File.dirname(__FILE__),"../../config/database.yml"))
# Allow environmental variable override on environment
if ENV['SSHSCANDATABASEENV']
environment = ENV['SSHSCANDATABASEENV']
end
case environment
when "test"
ActiveRecord::Base.establish_connection(config["test"])
when "development"
ActiveRecord::Base.establish_connection(config["development"])
when "production"
ActiveRecord::Base.establish_connection(config["production"])
else
raise "Unsupported environment specified, acceptable environments are test, development, or production"
end
end
def do_work
scan = SSHScan::Scan.find_by("state": "QUEUED")
# If work to do, then do it
if scan
scan.state = "RUNNING"
scan.worker_id = @worker_id
scan.save
@log.info("Starting Scan: #{scan.scan_id}")
options = {
"sockets" => [[scan.target,scan.port.to_s].join(":")],
"fingerprint_database" => @fingerprint_database_path,
"policy" => @policy_path,
"timeout" => 5,
}
scan_engine = SSHScan::ScanEngine.new
results = scan_engine.scan(options)
scan.state = "COMPLETED"
scan.worker_id = @worker_id
if results.first["compliance"]
scan.grade = results.first["compliance"]["grade"]
end
scan.raw_scan = results.first.to_json
scan.save
else
@log.info("No work available")
sleep @poll_interval
end
end
def run!
loop do
do_work
end
end
end

Просмотреть файл

@ -1,89 +0,0 @@
require 'spec_helper'
require 'ssh_scan_api/worker'
require 'ssh_scan'
require 'json'
describe SSHScan::Worker do
before do :each
@worker = SSHScan::Worker.new
@worker.set_environment("test")
# Start fresh with a new database every time
SSHScan::Scan.destroy_all
end
it "should have sane default behavior" do
expect(@worker.instance_variable_get(:@worker_id)).to match(/^[\w]+{8}-[\w]+{4}-[\w]+{4}-[\w]+{4}-[\w]+{12}$/)
expect(@worker.instance_variable_get(:@fingerprint_database_path)).to be_kind_of(::String)
expect(@worker.instance_variable_get(:@policy_path)).to be_kind_of(::String)
expect(@worker.instance_variable_get(:@poll_interval)).to eql(1)
end
it "should pull items off the queue and complete them" do
# Manually add a scan to the queue
scan = SSHScan::Scan.new do |s|
s.scan_id = SecureRandom.uuid
s.creation_time = Time.now
s.target = "sshscan.rubidus.com"
s.port = 22
s.state = "QUEUED"
s.save
end
# Verify the scan is in the queue
scan_from_queue = SSHScan::Scan.find_by("scan_id": scan.scan_id)
expect(scan_from_queue).to be_kind_of(SSHScan::Scan)
@worker.do_work
completed_scan = SSHScan::Scan.find_by("scan_id": scan.scan_id)
expect(completed_scan.state).to eql("COMPLETED")
expect(completed_scan.grade).to eql("A")
expect(completed_scan.worker_id).to match(/^[\w]+{8}-[\w]+{4}-[\w]+{4}-[\w]+{4}-[\w]+{12}$/)
expect(completed_scan.raw_scan).to be_kind_of(::String)
expect(JSON.parse(completed_scan.raw_scan)).to be_kind_of(::Hash)
end
it "should pull items off the queue and complete them in order" do
scan1 = SSHScan::Scan.new do |s|
s.scan_id = SecureRandom.uuid
s.creation_time = Time.now
s.target = "sshscan.rubidus.com"
s.port = 22
s.state = "QUEUED"
s.save
end
scan2 = SSHScan::Scan.new do |s|
s.scan_id = SecureRandom.uuid
s.creation_time = Time.now
s.target = "sshscan.rubidus.com"
s.port = 22
s.state = "QUEUED"
s.save
end
# Verify the scans are in the queue
scan1_from_queue = SSHScan::Scan.find_by("scan_id": scan1.scan_id)
expect(scan1_from_queue).to be_kind_of(SSHScan::Scan)
scan2_from_queue = SSHScan::Scan.find_by("scan_id": scan2.scan_id)
expect(scan1_from_queue).to be_kind_of(SSHScan::Scan)
@worker.do_work
completed_scan1 = SSHScan::Scan.find_by("scan_id": scan1.scan_id)
expect(completed_scan1.state).to eql("COMPLETED")
expect(completed_scan1.grade).to eql("A")
expect(completed_scan1.worker_id).to match(/^[\w]+{8}-[\w]+{4}-[\w]+{4}-[\w]+{4}-[\w]+{12}$/)
expect(completed_scan1.raw_scan).to be_kind_of(::String)
expect(JSON.parse(completed_scan1.raw_scan)).to be_kind_of(::Hash)
@worker.do_work
completed_scan2 = SSHScan::Scan.find_by("scan_id": scan2.scan_id)
expect(completed_scan2.state).to eql("COMPLETED")
expect(completed_scan2.grade).to eql("A")
expect(completed_scan2.worker_id).to match(/^[\w]+{8}-[\w]+{4}-[\w]+{4}-[\w]+{4}-[\w]+{12}$/)
expect(completed_scan2.raw_scan).to be_kind_of(::String)
expect(JSON.parse(completed_scan2.raw_scan)).to be_kind_of(::Hash)
end
end