Remove worker logic from API repo
This commit is contained in:
Родитель
18c5675bf9
Коммит
d357027aa3
|
@ -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
|
||||
|
|
13
docker/base
13
docker/base
|
@ -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
|
Загрузка…
Ссылка в новой задаче